ZOJ 3686 线段树

来源:互联网 发布:starbound mac 汉化 编辑:程序博客网 时间:2024/05/18 12:34

思路:给定一个树结构,每变化一个点其子树上的点都变,我们可以先深搜一次,给每个点编号,然后每个点能影响的点的编号是连续的一段,这样就把树结构转化为线性的,每个点对应于一个区间。之后就是线段树了。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct node{    int s,e;}p[400005];struct nnode{    int l,r,c,s;}t[800005];int fst[400005],next[400005],node[400005],en;int n,m;int cnt;void init(){    en=0;    cnt=0;    memset(fst,-1,sizeof(fst));}void add(int u,int v){    next[en]=fst[u];    fst[u]=en;    node[en]=v;    en++;}void build(int ll,int rr,int rot){    t[rot].l=ll;    t[rot].r=rr;    t[rot].s=0;    t[rot].c=0;    if(ll==rr)    {        return ;    }    int mid=(ll+rr)/2;    build(ll,mid,rot<<1);    build(mid+1,rr,rot<<1|1);}void dfs(int u){    p[u].s=++cnt;    for(int i=fst[u];i!=-1;i=next[i])    {        dfs(node[i]);    }    p[u].e=cnt;}void update(int ll,int rr,int rot){    if(t[rot].l==ll&&t[rot].r==rr)    {        t[rot].c=(t[rot].c^1);        t[rot].s=t[rot].r-t[rot].l+1-t[rot].s;    }    else    {        if(t[rot].c==1)        {            t[rot<<1].c=(t[rot<<1].c^1);            t[rot<<1].s=(t[rot<<1].r-t[rot<<1].l+1-t[rot<<1].s);            t[rot<<1|1].c=(t[rot<<1|1].c^1);            t[rot<<1|1].s=(t[rot<<1|1].r-t[rot<<1|1].l+1-t[rot<<1|1].s);            t[rot].c=0;        }        int mid=(t[rot].l+t[rot].r)/2;        if(rr<=mid)update(ll,rr,rot<<1);        else if(ll>mid)update(ll,rr,rot<<1|1);        else        {            update(ll,mid,rot<<1);            update(mid+1,rr,rot<<1|1);        }        t[rot].s=t[rot<<1].s+t[rot<<1|1].s;    }}int query(int ll,int rr,int rot){    if(t[rot].l==ll&&t[rot].r==rr)return t[rot].s;    else    {        if(t[rot].c==1)        {            t[rot<<1].c=(t[rot<<1].c^1);            t[rot<<1].s=(t[rot<<1].r-t[rot<<1].l+1-t[rot<<1].s);            t[rot<<1|1].c=(t[rot<<1|1].c^1);            t[rot<<1|1].s=(t[rot<<1|1].r-t[rot<<1|1].l+1-t[rot<<1|1].s);            t[rot].c=0;        }        int mid=(t[rot].l+t[rot].r)/2;        if(rr<=mid)return query(ll,rr,rot<<1);        else if(ll>mid)return query(ll,rr,rot<<1|1);        else        {            return query(ll,mid,rot<<1)+query(mid+1,rr,rot<<1|1);        }    }}int main(){    int u;    char str[10];    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        for(int i=2;i<=n;i++)        {            scanf("%d",&u);            add(u,i);        }        dfs(1);        build(1,n,1);        while(m--)        {            scanf("%s%d",str,&u);            if(str[0]=='o')            {                update(p[u].s,p[u].e,1);            }            else if(str[0]=='q')            {                cout<<query(p[u].s,p[u].e,1)<<endl;            }        }        cout<<endl;    }    return 0;}


原创粉丝点击