bzoj3159 决战

题目描述:

bz

咕了几个月的题解:

无脑$splay$+树剖。

论复制粘贴在考场上拉分的重要作用。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 50050;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,m,Rt,hed[N],cnt;
struct EG
{
    int to,nxt;
}e[N<<1];
void ae(int f,int t)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
int dep[N],siz[N],tp[N],son[N],fa[N],tin[N],tout[N],tim,pla[N];
void dfs1(int u,int f)
{
    fa[u]=f,siz[u]=1,dep[u]=dep[f]+1;
    for(int j=hed[u],to;j;j=e[j].nxt)if((to=e[j].to)!=f)
    {
        dfs1(to,u),siz[u]+=siz[to];
        if(siz[to]>siz[son[u]])son[u]=to;
    }
}
void dfs2(int u,int Top)
{
    tp[u]=Top,tin[u]=++tim,pla[tim]=u;
    if(son[u])
    {
        dfs2(son[u],Top);
        for(int j=hed[u],to;j;j=e[j].nxt)
            if((to=e[j].to)!=fa[u]&&to!=son[u])dfs2(to,to);
    }
    tout[u]=tim;
}
int get_lca(int x,int y)
{
    while(tp[x]!=tp[y])
    {
        if(dep[tp[x]]<dep[tp[y]])swap(x,y);
        x = fa[tp[x]];
    }
    return dep[x]<dep[y]?x:y;
}
struct Splay
{
    int w[N],mx[N],mn[N],rt,rtt,fa[N],ch[N][2],siz[N];
    ll tag[N],s[N];
    bool res[N];
    void add(int u,ll d)
    {
        if(u)w[u]+=d,tag[u]+=d,s[u]+=d*siz[u],mx[u]+=d,mn[u]+=d;
    }
    void rever(int u)
    {
        if(u)swap(ch[u][0],ch[u][1]),res[u]^=1;
    }
    void pushdown(int u)
    {
        if(tag[u])
        {
            add(ch[u][0],tag[u]);
            add(ch[u][1],tag[u]);
            tag[u]=0;
        }
        if(res[u])
        {
            rever(ch[u][0]);
            rever(ch[u][1]);
            res[u] = 0;
        }
    }
    void update(int x)
    {
        s[x]=s[ch[x][0]]+s[ch[x][1]]+w[x];
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
        mx[x]=max(w[x],max(mx[ch[x][0]],mx[ch[x][1]]));
        mn[x]=min(w[x],min(mn[ch[x][0]],mn[ch[x][1]]));
    }
    void rotate(int x)
    {
        int y = fa[x],z = fa[y],k = (ch[y][1]==x);
        ch[z][ch[z][1]==y]=x,fa[x]=z;
        ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y;
        ch[x][!k]=y,fa[y]=x;
        update(y),update(x);
    }
    int sta[N],tl;
    void down(int x)
    {
        tl = 0;
        while(x)sta[++tl]=x,x=fa[x];
        while(tl)pushdown(sta[tl--]);
    }
    void splay(int x,int goal)
    {
        down(x);
        while(fa[x]!=goal)
        {
            int y = fa[x],z = fa[y];
            if(z!=goal)
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)rt=x;
    }
    void splayy(int x,int goal)
    {
        down(x);
        while(fa[x]!=goal)
        {
            int y = fa[x],z = fa[y];
            if(z!=goal)
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)rtt=x;
    }
    int build(int l,int r,int f)
    {
        if(l>r)return 0;
        int mid = (l+r)>>1;
        fa[mid] = f;if(!f)rt=mid;
        ch[mid][0] = build(l,mid-1,mid);
        ch[mid][1] = build(mid+1,r,mid);
        update(mid);return mid;
    }
    void init()
    {
        fa[n+4]=n+3;ch[n+3][1]=n+4;rtt=n+3;
        siz[n+3]=2,siz[n+4]=1;
        mn[0]=0x3f3f3f3f,mx[0]=-0x3f3f3f3f;
    }
    int get_kth(int u,int k)
    {
        pushdown(u);
        int tmp = siz[ch[u][0]];
        if(k<=tmp)return get_kth(ch[u][0],k);
        else if(k==tmp+1)return u;
        else return get_kth(ch[u][1],k-1-tmp);
    }
    void split(int l,int r)
    {
        l = get_kth(rt,l),r = get_kth(rt,r+2);
        splay(l,0),splay(r,l);
    }
    void splitt(int l,int r)
    {
        l = get_kth(rtt,l),r = get_kth(rtt,r+2);
        splayy(l,0),splayy(r,l);
    }
    int get_kw(int k)
    {
        int x = get_kth(rt,k+1);return w[x];
    }
    ll get_sum(int l,int r)
    {
        split(l,r);
        return s[ch[ch[rt][1]][0]];
    }
    int get_max(int l,int r)
    {
        split(l,r);return mx[ch[ch[rt][1]][0]];
    }
    int get_min(int l,int r)
    {
        split(l,r);return mn[ch[ch[rt][1]][0]];
    }
    void Inc(int l,int r,int d)
    {
        split(l,r);
        add(ch[ch[rt][1]][0],d);
        update(ch[rt][1]),update(rt);
    }
    void mr(int l,int r)
    {
        split(l,r);int now = get_kth(rtt,2),las = ch[ch[rt][1]][0];
        splayy(now,0);fa[las]=n+3,ch[n+3][1]=las,ch[ch[rt][1]][0]=0;
        update(ch[rt][1]),update(rt),update(n+3),update(now);
    }
    void rvs()
    {
        splayy(n+3,0),splayy(n+4,n+3);
        rever(ch[ch[rtt][1]][0]);
    }
    void ml(int l,int r)
    {
        int xl = get_kth(rt,l),xr = get_kth(rt,l+1);
        splay(xr,0),splay(xl,xr);
        splitt(1,r-l+1);int now = ch[ch[rtt][1]][0];
        ch[ch[rtt][1]][0]=0,ch[ch[rt][0]][1]=now,fa[now]=ch[rt][0];
        update(ch[rt][0]),update(rt),update(ch[rtt][1]),update(rtt);
    }
}tr;
char op[10];
int lst[N],rst[N],tl;
ll queryS(int x,int y)
{
    ll ret = 0;
    while(tp[x]!=tp[y])
    {
        ret+=tr.get_sum(tin[tp[x]],tin[x]);
        x = fa[tp[x]];
    }
    return ret+tr.get_sum(tin[y],tin[x]);
}
int queryMax(int x,int y)
{
    int ret = -0x3f3f3f3f;
    while(tp[x]!=tp[y])
    {
        ret = max(ret,tr.get_max(tin[tp[x]],tin[x]));
        x = fa[tp[x]];
    }
    return max(ret,tr.get_max(tin[y],tin[x]));
}
int queryMin(int x,int y)
{
    int ret = 0x3f3f3f3f;
    while(tp[x]!=tp[y])
    {
        ret = min(ret,tr.get_min(tin[tp[x]],tin[x]));
        x = fa[tp[x]];
    }
    return min(ret,tr.get_min(tin[y],tin[x]));
}
int main()
{
    read(n),read(m),read(Rt);
    for(int i=1,u,v;i<n;i++)
    {
        read(u),read(v);
        ae(u,v),ae(v,u);
    }
    dfs1(Rt,0),dfs2(Rt,Rt);
    tr.build(1,n+2,0);tr.init();
    for(int i=1,x,y,w;i<=m;i++)
    {
        scanf("%s",op+1),read(x),read(y);
        if(dep[x]>dep[y])swap(x,y);
        if(op[1]=='I'&&op[3]=='c')
        {
            read(w);
            while(tp[y]!=tp[x])
            { 
                tr.Inc(tin[tp[y]],tin[y],w);
                y = fa[tp[y]];
            }
            tr.Inc(tin[x],tin[y],w);
        }else if(op[1]=='I'&&op[3]=='v')
        {
            tl = 0;
            while(tp[y]!=tp[x])
            {
                lst[++tl]=tin[tp[y]],rst[tl]=tin[y];
                tr.mr(lst[tl],rst[tl]);
                y = fa[tp[y]];
            }
            lst[++tl]=tin[x],rst[tl]=tin[y];
            tr.mr(lst[tl],rst[tl]);
            tr.rvs();
            for(int j=tl;j>=1;j--)
                tr.ml(lst[j],rst[j]);
        }else if(op[1]=='S')
        {
            int Lca = get_lca(x,y);
            ll ans = queryS(x,Lca);
            ans+=queryS(y,Lca);
            ans-=tr.get_kw(tin[Lca]);
            printf("%lld\n",ans);
        }else if(op[1]=='M'&&op[2]=='a')
        {
            int Lca = get_lca(x,y);
            int ans = max(queryMax(x,Lca),queryMax(y,Lca));
            printf("%d\n",ans);
        }else
        {
            int Lca = get_lca(x,y);
            int ans = min(queryMin(x,Lca),queryMin(y,Lca));
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

posted @ 2019-05-22 16:59  LiGuanlin  阅读(138)  评论(0编辑  收藏  举报