CodeForces877E 线段树lazy
来源:互联网 发布:全国ip网络广播系统 编辑:程序博客网 时间:2024/06/06 03:33
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:
- pow v describes a task to switch lights in the subtree of vertex v.
- 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.
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.
For each task get v print the number of rooms in the subtree of v, in which the light is turned on.
41 1 11 0 0 19get 1get 2get 3get 4pow 1get 1get 2get 3get 4
20012110
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;}
- CodeForces877E 线段树lazy
- pku3468 线段树lazy
- 线段树lazy操作
- JuQueen(线段树 lazy)
- 【例题】【线段树】lazy
- 线段树Lazy-tag
- 线段树--lazy思想
- HDU1698(线段树LAZY)
- 线段树lazy标记
- Lazy Salesgirl-线段树优化
- poj2777线段树+lazy思想
- 区间修改lazy线段树
- 线段树lazy标记??Hdu4902
- POJ2777线段树染色+lazy
- SYSU 1686 线段树 lazy
- 线段树入门&lazy思想
- hdu 1556 lazy线段树
- POJ3468【线段树lazy操作】
- php-redis配置使用
- 第1127期AI100_机器学习日报(2017-10-19)
- 12-面向对象(接口-细节)1 12-面向对象(接口-细节)2
- 第1130期AI100_机器学习日报(2017-10-22)
- vue学习第6天,还是组件
- CodeForces877E 线段树lazy
- JAVA中常用的高级集合类总结(包含Concurrent包下的并发集合类)
- [JZOJ5413]【NOIP2017提高A组集训10.22】清兰
- Exception in thread "main" java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provid
- win10下安装pygame
- 详细了解浏览器内核
- pip安装
- ajax 图片上传
- 【BigHereo 27】---T6-《信息系统开发与管理》---系统设计