[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\n",res);
        }
    }
    return 0;
}
posted @ 2017-07-06 13:57  FallDream  阅读(418)  评论(0编辑  收藏  举报