CodeForces877E 线段树lazy

来源:互联网 发布:全国ip网络广播系统 编辑:程序博客网 时间:2024/06/06 03:33
我的code超市了
E. Danil and a Part-time Job
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Danil decided to earn some money, so he had found a part-time job. The interview have went well, so now he is a light switcher.

Danil works in a rooted tree (undirected connected acyclic graph) with n vertices, vertex 1 is the root of the tree. There is a room in each vertex, light can be switched on or off in each room. Danil's duties include switching light in all rooms of the subtree of the vertex. It means that if light is switched on in some room of the subtree, he should switch it off. Otherwise, he should switch it on.

Unfortunately (or fortunately), Danil is very lazy. He knows that his boss is not going to personally check the work. Instead, he will send Danil tasks using Workforces personal messages.

There are two types of tasks:

  1. pow v describes a task to switch lights in the subtree of vertex v.
  2. get v describes a task to count the number of rooms in the subtree of v, in which the light is turned on. Danil should send the answer to his boss using Workforces messages.

A subtree of vertex v is a set of vertices for which the shortest path from them to the root passes through v. In particular, the vertex v is in the subtree of v.

Danil is not going to perform his duties. He asks you to write a program, which answers the boss instead of him.

Input

The first line contains a single integer n (1 ≤ n ≤ 200 000) — the number of vertices in the tree.

The second line contains n - 1 space-separated integers p2, p3, ..., pn (1 ≤ pi < i), where pi is the ancestor of vertex i.

The third line contains n space-separated integers t1, t2, ..., tn (0 ≤ ti ≤ 1), where ti is 1, if the light is turned on in vertex i and 0 otherwise.

The fourth line contains a single integer q (1 ≤ q ≤ 200 000) — the number of tasks.

The next q lines are get v or pow v (1 ≤ v ≤ n) — the tasks described above.

Output

For each task get v print the number of rooms in the subtree of v, in which the light is turned on.

Example
input
41 1 11 0 0 19get 1get 2get 3get 4pow 1get 1get 2get 3get 4
output
20012110
Note
The tree before the task pow 1.

The tree after the task pow 1.

#include <iostream>#include <queue>#include <cstring>#include<set>#include<cmath>#include<stdio.h>#include<queue>#include<vector>#include<map>#include<cstdio>#include<string.h>typedef long long ll;using namespace std;const int MAXM=400006;//int add[MAXM];int a[MAXM+5],st[MAXM+5], st2[MAXM+5];vector<int>vec[MAXM];int flip[MAXM];int fa[MAXM];ll cn;void build(int o){    if(vec[o].size()==0)        st[o]=a[o];    else{        for (int i=0; i<vec[o].size(); i++){            build(vec[o][i]);            st[o]+=st[vec[o][i]];        }        st[o]+=a[o];    }}void pushup(int o){    st[o]=st[o<<1]+st[o<<1|1];}/*void pushdown(int o,int l,int r){    if(add[o]){        add[o<<1]+=add[o];//左右儿子结点均加上父节点的更新值        add[o<<1|1]+=add[o];        int m=l+((r-l)>>1);        st[o<<1]+=add[o]*(m-l+1);//左右儿子结点均按照需要加的值总和更新结点信息        st[o<<1|1]+=add[o]*(r-m);        add[o]=0;//信息传递完之后就可以将父节点的更新信息删除    }}void update(int o,int l,int r,int ql,int qr,int addv){//ql、qr为需要更新的区间左右端点,addv为需要增加的值    if(ql<=l&&qr>=r){//与单点更新一样,当当前结点被需要更新的区间覆盖时        add[o]+=addv;//更新该结点的所需更新信息        st[o]+=addv*(r-l+1);//更新该结点信息        return;//根据lazy思想,由于不需要遍历到下层结点,因此不需要继续向下更新,直接返回    }    pushdown(o,l,r);//将当前结点的所需更新信息传递到下一层(其左右儿子结点)    int m=l+((r-l)>>1);    if(ql<=m)update(o<<1,l,m,ql,qr,addv);//当需更新区间在当前结点的左儿子结点内,则更新左儿子结点    if(qr>=m+1)update(o<<1|1,m+1,r,ql,qr,addv);//当需更新区间在当前结点的右儿子结点内,则更新右儿子结点    pushup(o);//递归回上层时一步一步更新回父节点}*/ll push(int x, int flipup){    if (vec[x].size()==0){        if ((flip[x]+flipup)&1) {            a[x]=1-a[x];            st[x]=a[x];        }        flip[x]=0;        /*cout<<"push "<<x<<endl;        cout<<"flipup+flipx="<<flipup+flip[x]<<endl;        cout<<"return "<<st[x]<<endl;*/        return st[x];    }    ll sum=0;    cn+=vec[x].size();    for (int i=0; i<vec[x].size(); i++){        sum+=push(vec[x][i], flipup+flip[x]);    }    if ((flip[x]+flipup)&1){        flip[x]=0;        a[x]=1-a[x];        st[x]=(a[x])+sum;        /*cout<<"push "<<x<<endl;        cout<<"flipup+flipx="<<flipup+flip[x]<<endl;        cout<<"return "<<st[x]<<endl;*/        return st[x];    }    else {        flip[x]=0;        st[x]=a[x]+sum;        /*cout<<"push "<<x<<endl;        cout<<"flipup+flipx="<<flipup+flip[x]<<endl;        cout<<"return "<<st[x]<<endl;*/        return st[x];    }}ll query(int x){//ql、qr为需要查询的区间    int tot=0;    for (int tmp=fa[x]; tmp!=-1; tmp=fa[tmp]){        if (flip[tmp]&1){            tot++;        }    }    //cout<<"tot="<<tot<<endl;    cn=0;    ll tmp=push(x, 0);    if (tot&1) return cn+1-tmp;    else return tmp;}/*void update(int x){    flip[x]++;int ori;    int chag=(vec[x].size()+1-st[x])-st[x];    for (int tmp=fa[x]; tmp!=-1; tmp=fa[tmp]){        ori=st[tmp];        st[tmp]+=chag;        cout<<tmp<<" + "<<chag;        chag=st[tmp]-ori;    }}*/int main(){    int n;    cin>>n;    for (int i=2; i<=n; i++){        int x;        scanf("%d", &x);        vec[x].push_back(i);        fa[i]=x;    }    fa[1]=(-1);    for (int i=1; i<=n; i++){        int x;        scanf("%d", &x);        a[i]=x;    }    build(1);    //memset(st1, st, sizeof(st));    /*for (int i=1; i<=n; i++)        cout<<"ss"<<st[i]<<endl;*/    int m;    cin>>m;    for (int i=1; i<=m; i++){        char inst[10];        scanf("%s", inst);        //cout<<"in="<<inst[0]<<endl;        if (inst[0]=='g'){            int x;            //cout<<"x="<<x<<endl<<endl;            scanf("%d", &x);            printf("%d\n", query(x));        }        else{            int x;            //cout<<"x="<<x<<endl<<endl;            scanf("%d", &x);            flip[x]++;            //flip[x]++;        }        //cout<<"i="<<i<<endl;    }    return 0;}
还是太年亲, 呵呵, 来一发网上大神的
#include<set>#include<map>#include<queue>#include<stack>#include<vector>#include<string>#include<math.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int MAXN= (int)2e5+10;const int MOD = (int)1e9+7;#define lson (rt<<1)#define rson (rt<<1|1)int sum[MAXN*4],flag[MAXN*4],vl[MAXN];void build(int l,int r,int rt){if(l==r){sum[rt]=vl[l];return ;}int mid=l+r>>1;build(l,mid,lson);build(mid+1,r,rson);sum[rt]=sum[lson]+sum[rson];}void pushdown(int l,int r,int rt){if(!flag[rt])return ;int len=r-l+1;sum[lson]=(len+1)/2-sum[lson];flag[lson]^=1;sum[rson]=(len)/2-sum[rson];flag[rson]^=1;//sum[rt]=sum[lson]+sum[rson];flag[rt]=0;}void update(int l,int r,int x,int y,int rt){if(l==x&&r==y){sum[rt]=r-l+1-sum[rt];flag[rt]^=1;return ;}pushdown(l,r,rt);int mid=l+r>>1;if(mid>=y)update(l,mid,x,y,lson);else if(mid<x)update(mid+1,r,x,y,rson);else update(l,mid,x,mid,lson),update(mid+1,r,mid+1,y,rson);sum[rt]=sum[lson]+sum[rson];}int query(int l,int r,int x,int y,int rt){//printf("%d %d %d %d %d\n",l,r,sum[rt],sum[7],flag[rt]);if(l==x&&r==y){return sum[rt];}//if(l==6&&r==7)printf("%d\n",flag[rt]);pushdown(l,r,rt);int mid=l+r>>1;if(mid>=y)return query(l,mid,x,y,lson);else if(mid<x) return query(mid+1,r,x,y,rson);else return query(l,mid,x,mid,lson)+query(mid+1,r,mid+1,y,rson);}struct edge{int to,nxt;}ed[MAXN<<1];int head[MAXN],cnt;void addedge(int u,int v){ed[cnt].to=v;ed[cnt].nxt=head[u];head[u]=cnt++;}int L[MAXN],R[MAXN],idx,a[MAXN];void dfs(int u){L[u]=++idx;vl[idx]=a[u];for(int i=head[u];i!=-1;i=ed[i].nxt){int v=ed[i].to;dfs(v);}R[u]=idx;}int main(){memset(head,-1,sizeof(head));int n;scanf("%d",&n);for(int i=2;i<=n;i++){int fa;scanf("%d",&fa);addedge(fa,i);}for(int i=1;i<=n;i++)scanf("%d",&a[i]);dfs(1);//for(int i=1;i<=n;i++)printf("%d %d %d\n",i,L[i],R[i]); build(1,n,1); int m;scanf("%d",&m);while(m--){char str[10];int x;scanf("%s%d",str,&x);if(str[0]=='g'){printf("%d\n",query(1,n,L[x],R[x],1));}else {update(1,n,L[x],R[x],1);}}return 0;}
#include <iostream>#include <queue>#include <cstring>#include<set>#include<cmath>#include<stdio.h>#include<queue>#include<vector>#include<map>#include<cstdio>#include<string.h>typedef long long ll;using namespace std;
const int MAXM=400006;//int add[MAXM];int a[MAXM+5],sum[MAXM+5], L[MAXM+5], R[MAXM+5], flag[MAXM+5], vl[MAXM+5];vector<int>vec[MAXM];int flip[MAXM];int fa[MAXM];
ll cn;void build(int x, int l, int r){    //cout<<"build "<<x<<l<<r<<endl;    if (l==r) {        sum[x]=vl[l];        return;    }    int mid=l+r>>1;    build(x<<1, l, mid);    build(x<<1|1, mid+1, r);    sum[x]=sum[x<<1]+sum[x<<1|1];
}
void pushdown(int x, int l, int r){    ///永远保证当前结点的sum是正确的,    //cout<<"push "<<x<<endl;    flip[x]=0;    int len=r-l+1;    /*sum[x<<1]=(len+1)/2-sum[x<<1];    sum[x<<1|1]=(len)/2-sum[x<<1|1];*/    int mid=l+r>>1;    sum[x<<1]=mid-l+1-sum[x<<1];    sum[x<<1|1]=r-mid-sum[x<<1|1];    flip[x<<1]^=1;    flip[x<<1|1]^=1;}
void update(int x, int l, int r, int l0, int r0){    if (l0<=l && r0 >=r){        sum[x]=r-l+1-sum[x];        flip[x]^=1;        return;        //return sum[x];    }    if (flip[x]) pushdown(x, l, r);    int mid=l+r>>1;    if (l0<=mid) update(x<<1, l, mid, l0, r0);    if (r0>=mid+1) update(x<<1|1, mid+1, r, l0, r0);    sum[x]=sum[x<<1]+sum[x<<1|1];}
ll query(int x, int l, int r, int l0, int r0){    //cout<<"query "<<x<<" "<<l<<r<<l0<<r0<<endl;    if (l0<=l && r0>=r) {        //cout<<"ret "<<sum[x]<<endl;        return sum[x];    }    if (flip[x]) pushdown(x, l, r);    int mid=l+r>>1;    if (l0>mid){        return query(x<<1|1, mid+1, r, l0, r0);    }    if (r0<mid+1){        return query(x<<1, l, mid, l0, r0);    }    else{        return query(x<<1, l, mid, l0, r0)+ query(x<<1|1, mid+1, r, l0, r0);    }}
int idx=0;void dfs(int x){    L[x]=++idx;    vl[idx]=a[x];    for (int i=0; i<vec[x].size(); i++)        dfs(vec[x][i]);    R[x]=idx;}
int main(){
    int n;    cin>>n;    for (int i=2; i<=n; i++){        int x;        scanf("%d", &x);        vec[x].push_back(i);    }    for (int i=1; i<=n; i++){        scanf("%d", &a[i]);    }    dfs(1);    build(1, 1, n);    memset(flip, 0, sizeof(flip));    /*for (int i=1; i<=n; i++)        cout<<"ss"<<st[i]<<endl;*/    int m;    cin>>m;
    for (int i=1; i<=m; i++){        char inst[10];        scanf("%s", inst);        //cout<<"in="<<inst[0]<<endl;        if (inst[0]=='g'){            int x;            //cout<<"x="<<x<<endl<<endl;            scanf("%d", &x);                /*for (int i=1; i<=7; i++){        cout<<"sum="<<sum[i]<<endl;    }*/            //  <<"L R="<<L[x]<<" "<<R[x]<<endl;            printf("%d\n", query(1, 1, n, L[x], R[x]));        }        else{            int x;            //cout<<"x="<<x<<endl<<endl;            scanf("%d", &x);            update(1, 1, n, L[x], R[x]);            //flip[x]++;        }        //cout<<"i="<<i<<endl;    }    return 0;}
永远保证要么节点上面的pushdown flag 给了节点后, 节点的区间值是正确的
update的时候 遇到整段区间符合 就给这个区间更新和 然后给个flag
flag永远作用于子节点
query update的时候就一直pushdown就可以了

非常好的题目