[GDKOI2015 day1]树

题目的所有描述

这里写图片描述
这里写图片描述

附上手打的样例

样例输入1

3
0 1 2
0 1 2
0 1
0 2
4
Ask
1 2 0
Change
0 1 2
Set
0 1 98
Ask
1 2 1

样例输出1

0
100

样例输入2

3
0 1 2
0 1 2
0 1
0 2
4
Ask 1 2 1
Change 0 1 2
Set 0 1 98
Ask 1 2 2

样例输出2

1
1


题解

建10棵线段树,表示10种颜色。
Set操作只需把表示原来颜色的树上的这个点删去,再在表示新颜色的树上加上就行了。
Change操作,当某个区间的左 /右儿子被修改范围覆盖时,交换这两种颜色的左 /右儿子。
Ask就简单了。


代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int Q=50005;
int ls[Q<<4],rs[Q<<4],cnt[Q<<4],n,tot=10;
int dep[Q],id[Q],be[Q],f[Q],bs[Q],si[Q],out[Q];
int last[Q],nn[Q<<1],e[Q<<1],inc=0,c[Q],v[Q];
void add(int x,int y)
{
    e[++inc]=y;
    nn[inc]=last[x];
    last[x]=inc;
}
inline int R()
{
    char o=getchar();
    int t=0;bool f=false;
    while(o>'9'||o<'0')
    {
        if(o=='-')f=true;
        o=getchar();
    }
    while(o<='9'&&o>='0')
    {
        t=10*t+int(o-'0');
        o=getchar();
    }
    return f?-t:t;
}
void fbc(int x)
{
    bs[x]=0,si[x]=1;
    int y,t,now=0;
    for(t=last[x];t;t=nn[t])
    {
        y=e[t];
        if(y==f[x])continue;
        dep[y]=dep[x]+1,f[y]=x;
        fbc(y);
        si[x]+=si[y];
        if(now<si[y])
            now=si[y],bs[x]=y;
    }
}
void cbc(int x,int now)
{
    id[x]=++inc,be[x]=now;
    if(bs[x]!=0)cbc(bs[x],now);
    int t,y;
    for(t=last[x];t;t=nn[t])
    {
        y=e[t];
        if(y==f[x]||y==bs[x])continue;
        cbc(y,y);
    }
    out[x]=inc;
}
void xiu(int now,int l,int r,int x,int v)
{
    if(l==r){
        cnt[now]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid){
        if(!ls[now])ls[now]=++tot;
        xiu(ls[now],l,mid,x,v);
    }
    else{
        if(!rs[now])rs[now]=++tot;
        xiu(rs[now],mid+1,r,x,v);
    }
    cnt[now]=cnt[ls[now]]+cnt[rs[now]];
}
int get(int now,int l,int r,int x,int y)
{
    if(x<=l&&y>=r)return cnt[now];
    int mid=(l+r)>>1,temp=0;
    if(x<=mid&&ls[now])temp+=get(ls[now],l,mid,x,y);
    if(y>mid&&rs[now])temp+=get(rs[now],mid+1,r,x,y);
    return temp;
}
void swip(int &nowl,int &nowr,int l,int r,int x,int y)
{
    if(x<=l&&y>=r){
        swap(nowl,nowr);
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid){
        if(!ls[nowl])ls[nowl]=++tot;
        if(!ls[nowr])ls[nowr]=++tot;
        swip(ls[nowl],ls[nowr],l,mid,x,y);
    }
    if(y>mid){
        if(!rs[nowl])rs[nowl]=++tot;
        if(!rs[nowr])rs[nowr]=++tot;
        swip(rs[nowl],rs[nowr],mid+1,r,x,y);
    }
    cnt[nowl]=cnt[ls[nowl]]+cnt[rs[nowl]];
    cnt[nowr]=cnt[ls[nowr]]+cnt[rs[nowr]];
}
int main()
{
    char o;
    int i,x,y;
    n=R();
    for(i=1;i<=n;i++)
        c[i]=R()+1;
    for(i=1;i<=n;i++)
        v[i]=R();
    for(i=1;i<n;i++)
    {
        x=R()+1,y=R()+1;
        add(x,y),add(y,x);
    }
    inc=0;
    dep[1]=1,f[1]=0;
    fbc(1);
    cbc(1,1);
    for(i=1;i<=n;i++)
        xiu(c[i],1,n,id[i],v[i]);
    for(i=1;i<=10;i++)
        c[i]=i;
    for(int m=R();m;--m)
        while(true)
        {
            o=getchar();
            if(o=='A')
            {
                int temp=0;
                x=R()+1,y=R()+1,i=R()+1;
                while(be[x]!=be[y])
                {
                    if(dep[be[x]]<dep[be[y]])swap(x,y);
                    temp+=get(c[i],1,n,id[be[x]],id[x]);
                    x=f[be[x]];
                }
                if(dep[x]>dep[y])swap(x,y);
                temp+=get(c[i],1,n,id[x],id[y]);
                printf("%d\n",temp);
                break;
            }
            if(o=='C')
            {
                i=R()+1,x=R()+1,y=R()+1;
                swip(c[x],c[y],1,n,id[i],out[i]);
                break;
            }
            if(o=='S')
            {
                x=R()+1,i=R()+1,y=R();
                for(int t=1;t<=10;t++)
                        xiu(c[t],1,n,id[x],0);
                xiu(c[i],1,n,id[x],y);
                break;
            }
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/includelhc/article/details/79735708
今日推荐