zoukankan      html  css  js  c++  java
  • [bzoj3159]决战

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    n,m<=50000

    考虑树链剖分,并对于每条重链维护一棵无旋treap

    15操作的时候把treap Merge到一起,打完标记,然后拆回去

    234操作直接查

    复杂度nlog^2n

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define MN 50000
    #define INF 2000000000 
    #define Sz(x) (x?x->size:0)
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    inline int Ran()
    {
        static int r=23333;
        r^=(r<<13);r^=(r>>17);r^=(r<<5);
        return r;    
    }
    struct Treap
    {
        Treap *l,*r;
        int size,k,mx,mn,x,val;ll sum;bool rev;
        Treap(){}
        Treap(int X){size=1;k=Ran();sum=mx=mn=x=X;rev=0;l=r=NULL;}
        void Add(int ad){sum+=1LL*size*ad;val+=ad;mn+=ad;mx+=ad;x+=ad;}
        void Rev(){swap(l,r);rev^=1;}
        void update()
        {
            size=Sz(l)+Sz(r)+1;mx=mn=sum=x;
            if(l) sum+=l->sum,mx=max(mx,l->mx),mn=min(mn,l->mn);
            if(r) sum+=r->sum,mx=max(mx,r->mx),mn=min(mn,r->mn); 
        }    
        void pushdown()
        {
            if(val) l?(l->Add(val),0):0,r?(r->Add(val),0):0,val=0;
            if(rev) l?(l->Rev(),0):0,r?(r->Rev(),0):0,rev=0; 
        }
    }*rt[MN+5];
    typedef pair<Treap*,Treap*> D;
    struct edge{int to,next;}e[MN*2+5];
    int n,m,Rt,head[MN+5],cnt=0,top[MN+5],fa[MN+5],size[MN+5],mx[MN+5],dep[MN+5];
    inline void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;    
    }
    
    D Split(Treap*x,int rk)
    {
        if(!x) return D(NULL,NULL);
        x->pushdown();int sz=Sz(x->l);D b;
        if(sz>=rk)
        {
            b=Split(x->l,rk);
            x->l=b.second;x->update();
            b.second=x;
        }
        else 
        {
            b=Split(x->r,rk-sz-1);
            x->r=b.first;x->update();
            b.first=x;    
        }
        return b;
    }
    
    Treap* Merge(Treap*x,Treap*y)
    {
        if(!x) return y;if(!y) return x;    
        if(x->k<y->k) 
        {
            x->pushdown();
            x->r=Merge(x->r,y);
            x->update();return x;    
        }
        else 
        {
            y->pushdown();
            y->l=Merge(x,y->l);
            y->update();return y;    
        }
    }
    
    void Pre(int x,int f)
    {
        fa[x]=f;size[x]=1;mx[x]=0;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=f)
            {
                dep[e[i].to]=dep[x]+1;Pre(e[i].to,x);
                size[x]+=size[e[i].to];
                if(size[e[i].to]>size[mx[x]]) mx[x]=e[i].to;
            }
    }
    
    void Dfs(int x,int tp)
    {
        top[x]=tp;Treap*now=new Treap(0);
        rt[tp]=Merge(rt[tp],now);
        if(mx[x]) Dfs(mx[x],tp);
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=fa[x]&&e[i].to!=mx[x])
                Dfs(e[i].to,e[i].to);
    }
    char op[15];
    int main()
    {
        n=read();m=read();dep[Rt=read()]=1;
        for(int i=1;i<=n;++i) rt[i]=NULL;
        for(int i=1;i<n;++i) ins(read(),read());
        Pre(Rt,0);Dfs(Rt,Rt);
        for(int i=1;i<=m;++i)
        {
            scanf("%s",op+1);int x=read(),y=read();
            if(op[1]=='I') 
            {
                if(dep[x]<dep[y]) swap(x,y);
                Treap*s=NULL;D ss;
                for(int t=x;t;t=fa[top[t]]) 
                {
                    ss=Split(rt[top[t]],dep[t]-dep[top[t]]+1);
                    s=Merge(ss.first,s);rt[top[t]]=ss.second;
                }
                D b=Split(s,dep[y]-1),c=Split(b.second,dep[x]-dep[y]+1);
                if(op[3]=='c') c.first->Add(read());
                else c.first->Rev();
                s=Merge(b.first,Merge(c.first,c.second));
                for(int t=x;t;t=fa[top[t]])
                {
                    D b=Split(s,dep[top[t]]-1);
                    rt[top[t]]=Merge(b.second,rt[top[t]]);s=b.first;
                }
            }
            else 
            {
                ll res=(op[2]=='i')?INF:0;    
                for(;top[x]!=top[y];x=fa[top[x]])
                {
                    if(dep[top[x]]<dep[top[y]]) swap(x,y);
                    D b=Split(rt[top[x]],dep[x]-dep[top[x]]+1);
                    if(op[1]=='S') res+=b.first->sum;
                    if(op[2]=='a') res=max(res,(ll)b.first->mx);
                    if(op[2]=='i') res=min(res,(ll)b.first->mn);    
                    rt[top[x]]=Merge(b.first,b.second);
                }
                if(dep[x]>dep[y]) swap(x,y); 
                D b=Split(rt[top[x]],dep[x]-dep[top[x]]);
                D c=Split(b.second,dep[y]-dep[x]+1);
                if(op[1]=='S') res+=c.first->sum;
                if(op[2]=='a') res=max(res,(ll)c.first->mx);
                if(op[2]=='i') res=min(res,(ll)c.first->mn);
                rt[top[x]]=Merge(b.first,Merge(c.first,c.second));
                printf("%lld
    ",res);
            }
        }
        return 0;
    }
  • 相关阅读:
    移动web开发资源大整合
    移动WEB模拟原声APP滑动删除
    jQuery的live绑定事件在mobile safari(iphone / ipad / ipod)上失效的解决方案
    精仿公众号菜单效果
    javascript markdown 解析器
    第四天
    第三天
    第二天
    第一天
    day5
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3159.html
Copyright © 2011-2022 走看看