• 【BZOJ3460】Jc的宿舍(树上莫队+树状数组)


    点此看题面

    大致题意: 一棵树,每个节点有一个人,他打水需要(T_i)的时间,每次询问两点之间所有人去打水的最小等待时间。

    伪·强制在线

    这题看似强制在线,但实际上,(pre mod 2)只能为(0)(1),因此只要将两种情况下的答案都求出来,最后视情况输出即可。

    这样就可以用离线算法乱搞了。

    树上莫队+树状数组

    其实,这道题是可以用树上莫队来做的。

    考虑当前已有若干人要去打水,现在新加入一个人,他的打水时间为(x),求改变的贡献值。

    显然,根据贪心的思想,我们应让打水时间越久的人越早打水

    则设有(rk)个人打水时间(>x)(val)为打水时间(le x)的人打水时间总和,则这个人所需等待时间为((rk+1)*x+val)

    不难发现,(rk)(val)两个值是可以用树状数组来进行维护的。

    这样这题就做完了。

    代码

    #include<bits/stdc++.h> 
    #define N 50000 
    #define LL long long 
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y) 
    #define swap(x,y) (x^=y^=x^=y) 
    using namespace std; 
    int n,query_tot,key,ee,a[N+5],lnk[N+5]; 
    struct edge 
    { 
        int to,nxt; 
    }e[(N<<1)+5]; 
    class Class_FIO 
    { 
        private: 
            #define Fsize 100000 
            #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++) 
            #define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,Fsize,stdout),Fout[(FoutSize=0)++]=ch)) 
            int Top,FoutSize;char ch,*A,*B,Fin[Fsize],Fout[Fsize],Stack[Fsize]; 
        public: 
            Class_FIO() {A=B=Fin;} 
            inline void read(int &x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));} 
            inline void readc(char &x) {while(isspace(x=tc()));} 
            inline void writeln(LL x) {if(!x) return pc('0'),pc('
    ');while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);pc('
    ');} 
            inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;} 
    }F; 
    class Class_CaptainMotao_on_Tree//树上莫队
    { 
        private: 
            #define bp(x) (((x)-1)/S+1) 
            #define F5(x) ((v=Di.get_val(a[t=x]),op[t]^=1)?(res+=1LL*(T.QSize(Di.cnt)-T.QSize(v)+1)*a[t]+T.QSum(v),T.Add(v,1,a[t]),0):(T.Add(v,-1,-a[t]),res-=1LL*(T.QSize(Di.cnt)-T.QSize(v)+1)*a[t]+T.QSum(v))) 
            int Q,S,op[N+5];LL ans[N+5][2];char opt[N+5]; 
            class Class_Dfser//DFS预处理
            { 
                private: 
                    #define LogN 16 
                    int cnt,Depth[N+5],fa[N+5][LogN+5]; 
                public: 
                    int s[(N<<1)+5],I[N+5],O[N+5];  
                    inline void Init(int x=1,int lst=0) 
                    { 
                        register int i; 
                        for(s[I[x]=++cnt]=x,i=1;i<=LogN;++i) fa[x][i]=fa[fa[x][i-1]][i-1]; 
                        for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(Depth[e[i].to]=Depth[fa[e[i].to][0]=x]+1,Init(e[i].to,x),0); 
                        s[O[x]=++cnt]=x; 
                    } 
                    inline int LCA(int x,int y) 
                    { 
                        register int i; 
                        for(Depth[x]<Depth[y]&&swap(x,y),i=0;Depth[x]^Depth[y];++i) ((Depth[x]^Depth[y])&(1<<i))&&(x=fa[x][i]); 
                        if(!(x^y)) return x; 
                        for(i=LogN;~i;--i) fa[x][i]^fa[y][i]&&(x=fa[x][i],y=fa[y][i]); 
                        return fa[x][0]; 
                    } 
            }D; 
            class Class_Discretization//离散化
            { 
                private: 
                    int data[N+5]; 
                public: 
                    int cnt; 
                    inline void Init(int len,int *num)  
                    { 
                        for(register int i=1;i<=len;++i) data[i]=num[i]; 
                        sort(data+1,data+len+1),cnt=unique(data+1,data+len+1)-data-1; 
                    } 
                    inline int get_val(int x) 
                    { 
                        register int l=1,r=cnt,mid; 
                        for(mid=l+r>>1;l<=r;mid=l+r>>1) data[mid]<x?l=mid+1:r=mid-1; 
                        return l; 
                    } 
            }Di; 
            class Class_TreeArray//树状数组
            { 
                private: 
                    #define lowbit(x) (x&-x) 
                    int Size[N+5];LL Sum[N+5]; 
                public: 
                    int len; 
                    inline void Add(int pos,int val1,int val2) {while(pos<=len) Size[pos]+=val1,Sum[pos]+=val2,pos+=lowbit(pos);} 
                    inline int QSize(int pos,int res=0) {while(pos) res+=Size[pos],pos-=lowbit(pos);return res;} 
                    inline LL QSum(int pos,LL res=0) {while(pos) res+=Sum[pos],pos-=lowbit(pos);return res;} 
            }T; 
            struct Query 
            { 
                int l,r,pos,op,bl,flag; 
                Query(int x=0,int y=0,int p=0,int o=0,int b=0,int f=0):l(x),r(y),pos(p),op(o),bl(b),flag(f){} 
                inline friend bool operator < (Query x,Query y) {return x.bl^y.bl?x.bl<y.bl:(x.bl&1?x.r<y.r:x.r>y.r);} 
            }q[(N<<1)+5]; 
        public: 
            inline void Solve() 
            { 
                int i,x,y,z,k,s=1,t,v,L=1,R=0;LL res=0,lst_ans=0; 
                for(D.Init(),Di.Init(n,a),T.len=Di.cnt,S=sqrt(n),i=1;i<=query_tot;++i)//每个询问分pre%2的值存储两个
                { 
                    if(F.readc(opt[i]),F.read(k),opt[i]^'Q') {s=k;continue;} 
                    D.I[x=k%n+1]>D.I[y=s]&&swap(x,y),q[++Q]=(z=D.LCA(x,y))^x?Query(D.O[x],D.I[y],i,0,bp(D.O[x]),z):Query(D.I[x],D.I[y],i,0,bp(D.I[x]),0); 
                    D.I[x=(k+key)%n+1]>D.I[y=s]&&swap(x,y),q[++Q]=(z=D.LCA(x,y))^x?Query(D.O[x],D.I[y],i,1,bp(D.O[x]),z):Query(D.I[x],D.I[y],i,1,bp(D.I[x]),0); 
                } 
                for(sort(q+1,q+Q+1),i=1;i<=Q;++i)//处理询问
                { 
                    while(R<q[i].r) F5(D.s[++R]);while(L>q[i].l) F5(D.s[--L]);while(R>q[i].r) F5(D.s[R--]);while(L<q[i].l) F5(D.s[L++]); 
                    q[i].flag&&F5(q[i].flag),ans[q[i].pos][q[i].op]=res,q[i].flag&&F5(q[i].flag); 
                } 
                for(i=1;i<=query_tot;++i) opt[i]^'C'&&(F.writeln(lst_ans=ans[i][lst_ans&1]),0);//输出答案
            } 
    }C; 
    int main() 
    { 
        register int i,x,y;register char op; 
        for(F.read(n),F.read(query_tot),F.read(key),i=1;i<=n;++i) F.read(a[i]); 
        for(i=1;i<=n;++i) F.read(x),add(x,i); 
        return C.Solve(),F.clear(),0; 
    }
    
  • 相关阅读:
    C#--跨线程更新UI--实时显示POST请求传过来的数据
    C#--序列化--JSON和对象互转方法
    C#--winform--Label标签的文字居中
    C#--自定义控件-panel控件(渐变色,文字的绘制)
    C#--自定义控件-开发LED指示灯控件(带闪烁效果)
    艾而特--ModbusTcp通讯测试
    C#--各种方法总结(静态,构造,析构,虚方法,重写方法,抽象,扩展)
    C#--特性的运用试验
    C#--特性基础
    C#--无法将lambda表达式转换为类型‘Delegate’,原因是它不是委托类型
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3460.html
Copyright © 2020-2023  润新知