bzoj1103 [POI2007]大都市meg

bzoj1103 [POI2007]大都市meg


(感觉自己越来越懒了。。。不想放链接)


BIT练手题。
一棵边权为1的树,操作为将一条边权改为0和查询根到某点路径。
弄个树状数组,存一下根到所有点的路径。查询是单点查询,然后修改是区间修改
所以是区间修改单点查询的BIT
记个dfs序就可以做到啦
还有此题边都是从上至下的,方便判断了233

// It is made by XZZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define lb(o) (o&-o)
typedef long long ll;
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return flg?-x:x;
}
const int maxn=250020;
int t[maxn],n;
il vd add(int i,int num){while(i<=n)t[i]+=num,i+=lb(i);}
il vd Plus(int l,int r){add(l,1),add(r+1,-1);}
il vd Minus(int l,int r){add(l,-1),add(r+1,1);}
il int sum(int i){int ret=0;while(i)ret+=t[i],i-=lb(i);return ret;}
int fir[maxn],dis[maxn],nxt[maxn],id;
int dfn[maxn],siz[maxn];
il vd _add(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
il vd dfs(int x,int fa=-1){
    dfn[x]=++dfn[0],siz[x]=1;
    erep(i,x)if(dis[i]^fa)dfs(dis[i],x),siz[x]+=siz[dis[i]];
    Plus(dfn[x],dfn[x]+siz[x]-1);
}
char opt[3];
int main(){
    int a,b;n=gi();
    rep(i,2,n)a=gi(),b=gi(),_add(a,b);
    dfs(1);
    int m=gi()+n-1;
    while(m--){
    scanf("%s",opt);
    if(opt[0]=='A')a=max(gi(),gi()),Minus(dfn[a],dfn[a]+siz[a]-1);
    else printf("%d\n",sum(dfn[gi()])-1);
    }
    return 0;
}
posted @ 2017-09-27 15:22  菜狗xzz  阅读(174)  评论(0编辑  收藏  举报