zoukankan      html  css  js  c++  java
  • 【好题】线段树区间合并(CDQ分治)——cf1316F

    /*
    离线读入所有值后离散化 
    题意要求的是,sum{ ai*2^(i-1)*aj*2^(n-j) }
     
    分析这个式子,考虑进行分治
        区间[l,r]的 sum{ ai*2^(i-l)*aj*2^(r-j) }
        可以将式子分成 ai*2^(i-l) 和 aj*2^(r-j)两部分看,
        线段树维护四个值,sum,pre,suf,size:分别表示这个
            区间的答案,
            ai*2^(i-l)的和
            aj*2^(r-j)的和
            区间有效元素个数
        那么当两个区间合并时
            sum = suml*2^sizer + sumr*2^sizel + prel*sufr,对应i,j都从左区间里出,i,j都从右区间里出,i,j从左右区间出 
            pre = prel + prer*2^sizel,对应左区间的pre,右区间的pre*左区间的元素个数 
            suf = sufr + sufl*2^sizer
            size = sizel + sizer 
    初始值:sum=0,size=0,pre=0,suf=0
    考虑位置i的值变为x 
         下降到叶子结点:size=1,pre=suf=x 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define mod 1000000007
    #define N 600005
     
    ll Pow(ll a,ll b){
        ll res=1;
        while(b){
            if(b%2)res=res*a%mod;
            b>>=1;a=a*a%mod;
        }
        return res;
    }
    ll P[N];
     
    struct Node{
        int id,x;
    }q[N<<1];
    ll n,p[N],Q; 
     
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    struct Seg{
        ll sum,pre,suf,size;
    }s[N<<2];
    Seg merge(Seg A,Seg B){
        Seg res;
        res.sum=(A.sum*P[B.size]%mod+B.sum*P[A.size]%mod+A.pre*B.suf%mod)%mod;
        res.pre=(A.pre+B.pre*P[A.size]%mod)%mod;
        res.suf=(B.suf+A.suf*P[B.size]%mod)%mod;
        res.size=(A.size+B.size)%mod;
        return res;
    }
    void update(int pos,ll x,int l,int r,int rt){
        if(l==r){
            s[rt].sum=0;
            s[rt].pre=s[rt].suf=x;
            if(x!=0)s[rt].size=1;
            else s[rt].size=0;
            return;
        }
        int m=l+r>>1;
        if(pos<=m)update(pos,x,lson);
        else update(pos,x,rson);
        s[rt]=merge(s[rt<<1],s[rt<<1|1]);
    }
     
    int pos1[N],pos2[N],m;
    struct OP{
        int id,x;
    }op[N<<1];
    int cmp(OP a,OP b){return a.x<b.x;}
     
    int main(){
        P[0]=1;
        for(int i=1;i<=300000;i++)P[i]=P[i-1]*2ll%mod;
        
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&p[i]);
            op[i].id=i;op[i].x=p[i];
        }
        scanf("%lld",&Q);
        for(int i=1;i<=Q;i++){
            scanf("%lld%lld",&q[i].id,&q[i].x);
            op[i+n].id=i+n;
            op[i+n].x=q[i].x;
        }
        m=n+Q;
        
        sort(op+1,op+1+n+Q,cmp);
        for(int i=1;i<=n+Q;i++){
            if(op[i].id<=n)
                pos1[op[i].id]=i;
            else pos2[op[i].id-n]=i;
        }
        
        memset(s,0,sizeof s);
        for(int i=1;i<=n;i++)
            update(pos1[i],p[i],1,m,1);
        
        ll base=Pow(P[n],mod-2);
        printf("%lld
    ",s[1].sum*base%mod);
        for(int i=1;i<=Q;i++){
            update(pos1[q[i].id],0,1,m,1);
            update(pos2[i],q[i].x,1,m,1);
            cout<<s[1].sum*base%mod<<'
    ';    
            pos1[q[i].id]=pos2[i];    
        }
    }
  • 相关阅读:
    web前端【第十四篇】Bootstrap简单使用
    web前端【第十三篇】jQuery扩展和事件
    web前端【第十二篇】jQuery文档相关操作
    web前端【第十一篇】jQuery属性相关操作
    页面组件
    索引
    前端基础
    pymysql与mysql各功能
    mysql数据操作
    mysql表相关操作
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12822673.html
Copyright © 2011-2022 走看看