牛客网暑期ACM多校训练营(第五场)F take【线段树】

https://www.nowcoder.com/acm/contest/143/F

题意:给出一条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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值