1. 程式人生 > >牛客網暑期ACM多校訓練營(第五場)F take【線段樹】

牛客網暑期ACM多校訓練營(第五場)F take【線段樹】

題意:給出一條n個節點的路,從1走到n,每個點有一定概率出現一個價值為w的鑽石,如果這個鑽石比手裡的鑽石大,他就把之前的扔了選這個。求扔的期望。

分析:
每一個點的扔的概率為,之前比它大的鑽石都沒有出現的概率。
那麼我們就可以通過線段樹來維護這個概率,用字首積實現。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn = 1e5
+ 12; #define ll long long int #define Build build #define Node node #define charmax(a,b) a=max(a,b) #define charmin(a,b) a=min(a,b) #define clr(a,b) memset(a,b,sizeof a) #define mod 998244353 #define rmod 828542813 ll a[5*maxn]; //I'm very sorry for my friends and our team "goodbye".That's not my time to say goodbye.I'm back now! ——Irish_Moonshine
struct node { int x, id, pos; bool operator < (const node &a) const { if (x > a.x || x == a.x&&id < a.id) return 1; return 0; } }s[2*maxn]; void Build(int l, int r, int x) { int m; if (l == r) { a[x] = 1; return; } m = (l + r) / 2; build(l, m, x * 2
); build(m + 1, r, x * 2 + 1); a[x] = 1; } void update(int l, int r, int x, int A, int B) { int m; if (l == r) { a[x] = 1ll * (100 - B)*rmod%mod; return; } m = (l + r) / 2; if (A <= m) update(l, m, x * 2, A, B); else update(m + 1, r, x * 2 + 1, A, B); a[x] = a[x * 2] * a[x * 2 + 1] % mod; } ll query(int l, int r, int x, int A, int B) { int m; ll ans = 1; m = (l + r) / 2; if (l >= A && r <= B) return a[x]; if (A <= m) ans = ans * query(l, m, x * 2, A, B) % mod; if (B >= m + 1) ans = ans * query(m + 1, r, x * 2 + 1, A, B) % mod; return ans; } ll qkm(ll a, ll b) { ll ans = 1; while(b > 0) { if (b % 2) ans = ans * a%mod; a = a * a%mod; b /= 2; } return ans; } int main() { ll ans=0, n; scanf("%lld", &n); for (int i = 1; i <= n; i++) { scanf("%d %d", &s[i].pos, &s[i].x); s[i].id = i; } sort(s + 1, s + 1 + n); Build(1, n, 1); for (int i = 1; i <= n; i++) { ans = (ans + query(1, n, 1, 1, s[i].id)*s[i].pos%mod*rmod) % mod; update(1, n, 1, s[i].id, s[i].pos); } printf("%lld\n", ans); return 0; }