codeforces 877 problem E Danil and a Part-time Job 【dfs序 + 线段树区间异或修改】
2017-11-06 15:11
465 查看
传送门
//题意: 给定一颗有根(1 )树,树上每一个点起始都有一个值(0或1),然后有两个操作,pow x把以 x为根的子树全部异或1, get x输出以x为根的子树中有多少个1.
//思路: 就是一个最裸的dfs序 + 线段树异或修改的,细节请看代码. 注意就是求一个区间中的1,那么就是区间长度-此时区间的值, 然后就是修改下lazy标记处就是了. 还有就是线段树中是dfs序的一些线段,所以在build过程中我们还需要知道此时的线段在树中对应的哪一个点,这样才能初始化.
AC Code
//题意: 给定一颗有根(1 )树,树上每一个点起始都有一个值(0或1),然后有两个操作,pow x把以 x为根的子树全部异或1, get x输出以x为根的子树中有多少个1.
//思路: 就是一个最裸的dfs序 + 线段树异或修改的,细节请看代码. 注意就是求一个区间中的1,那么就是区间长度-此时区间的值, 然后就是修改下lazy标记处就是了. 还有就是线段树中是dfs序的一些线段,所以在build过程中我们还需要知道此时的线段在树中对应的哪一个点,这样才能初始化.
AC Code
const int maxn = 2e5+5; int cas=1; int a[maxn]; int cnt,head[maxn]; int p1[maxn],p2[maxn]; int pre[maxn]; struct node { int to,next; }e[maxn<<1]; void add(int u,int v) { e[cnt] = (node){v,head[u]}; head[u] = cnt++; } int ti; void dfs_id(int u,int fa) { p1[u] = ++ti; pre[ti] = u; for(int i=head[u]; ~i ; i = e[i].next){ int to = e[i].to; if(fa == to) continue; dfs_id(to,u); } p2[u] = ti; } //p1存的是第一次遇到时序号,p2是第二次遇到的序号. //那么结点u及其子树存在的连续区间就是p1[u] - p2[u]. struct Tree{ int tl, tr, sum ,lazy; void fun(int tot) { lazy ^= 1; sum = tot - sum; } } tree[maxn<<2]; void pushup(int id) { tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum; } void pushdown(int id,int l,int r) { if(tree[id].lazy){ int mid = (l+r)>>1; tree[id<<1].fun(mid-l+1); tree[id<<1|1].fun(r-mid); tree[id].lazy = 0; } } void build(int id,int l,int r) { tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0; if(l == r){ tree[id].sum = a[pre[l]]; return ; } int mid = (l+r) >> 1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); pushup(id); } void update(int id,int st,int ed) { int l=tree[id].tl, r=tree[id].tr; if(st <= l && r <= ed){ tree[id].fun(r-l+1); return ; } pushdown(id,l,r); int mid = (l+r) >> 1; if(st <= mid) update(id<<1,st,ed); if(ed > mid) update(id<<1|1,st,ed); pushup(id); } int ans; void query(int id,int ql,int qr) { int l = tree[id].tl , r = tree[id].tr; if(ql <= l && r <= qr) { ans += tree[id].sum; return ; } pushdown(id,l,r); int mid = (l+r) >> 1; if(ql <= mid) query(id<<1,ql,qr); if(qr > mid) query(id<<1|1,ql,qr); } void solve() { int n; scanf("%d",&n); ti = 0; Fill(pre,0); cnt = 0; Fill(head,-1); for(int i=2;i<=n;i++){ int u; scanf("%d",&u); add(i,u); add(u,i); } for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } dfs_id(1,-1); build(1,1,n); int q; scanf("%d",&q); while(q--){ string s; cin >> s; int u; scanf("%d",&u); if(s == "get"){ ans = 0; query(1,p1[u],p2[u]); printf("%d\n",ans); } else{ update(1,p1[u],p2[u]); } } }
相关文章推荐
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job (dfs序树型转线性 线段树区间修改区间查询)
- Codeforces Round #442 (Div. 2)-E-Danil and a Part-time Job(DFS序+线段树区间更新)
- Codeforces-877E:Danil and a Part-time Job(DFS序列+线段树)
- Codeforces 877 E Danil and a Part-time Job(线段树+dfs序)
- codeforces 877E. Danil and a Part-time Job (DFS序列+线段树)
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job (dfs序 + 线段树)
- Codeforces Round #442E-dfs序&线段树的区间更新区间查询-Danil and a Part-time Job
- Codeforces Round #442 (Div. 2) 877 E. Danil and a Part-time Job DFS序 线段树
- Danil and a Part-time Job codeforces dfs序,线段树
- SPOJ IITWPC4F - Gopu and the Grid Problem (双线段树区间修改 区间查询)
- CodeForces 276E - Little Girl and Problem on Trees 区间更新..N+1个线段树
- CodeForces 877E Danil and a Part-time Job (dfs序+线段树)
- 简单树刨+线段树模板 877E - Danil and a Part-time Job
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job (dfs序+线段树)
- codeforces 877 problem B Nikita and string 【思维 + 前后缀思想】
- Codeforces 295A Greg and Array 线段树区间累加,单点询问
- [省选前题目整理][POJ 3468]A Simple Problem with Integers(线段树区间修改)
- VK Cup 2015 - Round 1 E. Rooks and Rectangles 线段树 定点修改,区间最小值
- POJ 3468 A Simple Problem with Integers 线段树区间修改
- 877E - Danil and a Part-time Job