BZOJ1103: [POI2007]大都市meg

来源:互联网 发布:淘宝密码对的登不上 编辑:程序博客网 时间:2024/06/05 05:12

BZOJ1103: [POI2007]大都市meg

括号序·树状数组

题解:

首先求出括号序。如样例为1455422331
将进栈时打上标记1,出栈时打标记-1,这样已经退出的点的两个标记就会互相抵消
然后出栈序号与1号序号之间的权值和-1即为答案(排除1的影响)
修改时只要将对应标记变为0就可以了

Code:

#include <iostream>#include <cstring>#include <cstdio>#define D(x) cout<<#x<<" = "<<x<<"  "#define E cout<<endlusing namespace std;const int N = 500005;int n,m,tim, s[N],t[N];struct Edge{    int to,next;} e[N*2];int ec=0, head[N];void add(int a,int b){    ec++; e[ec].to=b; e[ec].next=head[a]; head[a]=ec;}struct BIT{    int c[N*2], sz;    inline int lowbit(int x){ return x&(-x); }    void init(int _sz){ sz=_sz; memset(c,0,sizeof(c)); }    void add(int x,int d){ while(x<=sz){ c[x]+=d; x+=lowbit(x); } }    int sum(int x){ int ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; }} bit;void dfs(int x,int f){    s[x]=++tim;    for(int i=head[x];i;i=e[i].next){        int v=e[i].to;        if(v==f) continue;        dfs(v,x);    }    t[x]=++tim;}int main(){    scanf("%d",&n);    int a,b; char op[5];    for(int i=1;i<n;i++){        scanf("%d%d",&a,&b);        add(a,b); add(b,a);    }    dfs(1,0); bit.init(tim);    for(int i=2;i<=n;i++){        bit.add(s[i],1); bit.add(t[i],-1);    }    scanf("%d",&m); m=m+n-1;    for(int i=1;i<=m;i++){        scanf("%s",op);        if(op[0]=='A'){            scanf("%d%d",&a,&b);            bit.add(s[b],-1); bit.add(t[b],1);        }        else{            scanf("%d",&a);            printf("%d\n",bit.sum(s[a]));        }    }}
原创粉丝点击