zoukankan      html  css  js  c++  java
  • [CF1316F] Battalion Strength

    定义一个 (n) 元序列 (p_i),如果 (n=1),则序列权值为 (0),否则序列权值就是原序列排序后相邻两项乘积的和。现在等概率地选出一个子序列,问它的权值的期望是多少。支持动态单点修改。

    Solution

    对于静态情况,答案为

    [sum_{i=1}^n sum_{j=i+1}^n frac{p_i p_j}{2^{j-i+1}} ]

    考虑用线段树维护,对于区间 ([l,r]),我们设 (val) 为当前区间权值,(lv=sum_{i=l}^r p_i2^{i-l})(rv=sum_{i=l}^r p_i/2^{i-l+1})(sz) 是当前区间内数的个数,则

    [val=val_L+val_R+frac{1}{2} vl_Lvr_R/2^{sz_L} \ sz=sz_L+sz_R \ vl=vl_L+vl_R2^{sz_L} \ vr=vr_L+vr_R/2^{sz_L} ]

    对于单点 (a),它的 (val=0, sz=1, vl=a, vr=a/2)

    考虑到序列中有重复元素,我们先将所有元素(包括修改的)一起读进来排序,然后将原始的先激活,修改后的先不激活((val=0,sz=0,vl=0,vr=0)),一起挂在线段树上

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    const int mod =1e+9+7;
    const int dbg = 0;
    
    struct item {
        int v,x,t;
        bool operator < (const item &b) {
            return v < b.v;
        }
    } I[N];
    int n,m,seq[N],src[N],m1[N],m2[N],pos[N],p[N],iqp[N],qp[N];
    
    int qpow(int p,int q) {
        return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;
    }
    
    int inv(int p) {
        return qpow(p,mod-2);
    }
    
    struct node {
        int val,sz,vl,vr;
    } a[N*3];
    
    node merge(node l,node r) {
        node ret;
        ret.val=(l.val+r.val+l.vl*r.vr%mod*iqp[l.sz]%mod)%mod;
        ret.sz=l.sz+r.sz;
        ret.vl=(l.vl+r.vl*qp[l.sz])%mod;
        ret.vr=(l.vr+r.vr*iqp[l.sz])%mod;
        return ret;
    }
    
    void open(int p,int l,int r,int x) {
        if(l==r) {
            a[p]={0,1,I[x].v,I[x].v*inv(2)%mod};
        }
        else {
            if(x<=(l+r)/2) open(p*2,l,(l+r)/2,x);
            else open(p*2+1,(l+r)/2+1,r,x);
            a[p]=merge(a[p*2],a[p*2+1]);
        }
    }
    
    void open(int x) {
        if(dbg) cout<<"open "<<x<<endl;
        open(1,1,n+m,x);
    }
    
    void close(int p,int l,int r,int x) {
        if(l==r) {
            a[p]={0,0,0,0};
        }
        else {
            if(x<=(l+r)/2) close(p*2,l,(l+r)/2,x);
            else close(p*2+1,(l+r)/2+1,r,x);
            a[p]=merge(a[p*2],a[p*2+1]);
        }
    }
    
    void close(int x) {
        if(dbg) cout<<"close "<<x<<endl;
        close(1,1,n+m,x);
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=0;i<=1e6;i++) {
            iqp[i]=inv(qpow(2,i));
            qp[i]=qpow(2,i);
        }
        for(int i=1;i<=n;i++) {
            cin>>p[i];
            I[i].v=p[i];
            I[i].x=i;
            I[i].t=0;
        }
        cin>>m;
        for(int i=1;i<=m;i++) {
            int t1,t2;
            cin>>t1>>t2;
            m1[i]=t1;
            m2[i]=t2;
            I[n+i].v=t2;
            I[n+i].x=i;
            I[n+i].t=1;
        }
        sort(I+1,I+n+m+1);
        for(int i=1;i<=n+m;i++) {
            src[i]=I[i].v;
            if(I[i].t==0) {
                seq[I[i].x]=i;
            }
            else {
                pos[I[i].x]=i;
            }
        }
        for(int i=1;i<=n;i++) {
            open(seq[i]);
        }
        cout<<a[1].val<<endl;
        for(int i=1;i<=m;i++) {
            close(seq[m1[i]]);
            open(pos[i]);
            seq[m1[i]]=pos[i];
            cout<<a[1].val<<endl;
        }
    }
    
    
  • 相关阅读:
    test
    flash链接需要后台调用时的插入flash方法
    js验证码倒计时
    设置Cookie
    用in判断input中的placeholder属性是否在这个对象里
    常用的正则表达式规则
    webApp添加到iOS桌面
    .substr()在字符串每个字母前面加上一个1
    PAT 甲级1001 A+B Format (20)(C++ -思路)
    PAT 1012 数字分类 (20)(代码+测试点)
  • 原文地址:https://www.cnblogs.com/mollnn/p/12463644.html
Copyright © 2011-2022 走看看