CSU 1322 ZY‘s new company(线段树维护bfs序)
来源:互联网 发布:网络暴力议论文 编辑:程序博客网 时间:2024/06/03 05:51
转载声明:http://blog.csdn.net/alpc_neverfarewell/article/details/39160735
题意:
zzy开了一家公司,然后他为公司制定了人事制度:为每个员工都定一个直接的上属(除了zzy自己),这样就把公司表示成了一个树形的人事关系图,树的最顶端就是zzy自己。如果a的直接上属是b则称a是b的一级下属,接下去的依次称为2级、3级……k级下属。
由于如zzy奇葩的想法,他将改变一部分员工的工资,方法依旧是将员工原来的工资异或一个数,得到新的工资。
(这是中文题意,,不可能看不懂吧)
个人感想:
这道题目很有意思,就是有一个又有趣的思想,用线段树维护bfs序,然后通过最近公共祖先(LCA),加上二分就可以找到当前 老板 的c级员工的范围.
这道题还给了个重要的思想,就是区间异或和,这我也没接触过,一道题补了好多知识点,维护bfs序这个我是从来没想到过的,确实不会,
首先先做一遍bfs
我们就可以知道每个深度的区间范围
知道这个有有什么用?我们可以对深度范围进行二分,找到对应的父节点的c级员工节点范围并用线段树更新
例如 现在我要找2的 1级员工
我们知道 depth[2]+1==3
第3层的范围是 4-8.
那么我们就二分这个区间点,并且往上走c级
我们就要找到一个 parent[x][c]==2 最左节点, 和parent[y][c]>2的左的y,然后y-1 就是==2的最右节点了, 然后就可以用线段树维护
我觉得有点神奇,..只是我对这个理解不深啊,
其实我就看了一会转载的博客我就懂了..
我出的最大问题不在建树,只是二分,
因为有可能所查询的节点 根本没c级员工,那只是别人的位置有而已
那么我怎么二分出来 并且 判断这个区间(x,y)合法?
我一直习惯用(r-l>1) 进行二分,这样做有点难度就是 可能你2个点刚好相差1,所有两个位置都没检测,那还要特殊处理,那就好麻烦了…
所以啊,还是我修行不够啊..
挺好的一道题目,值得深思.
分析:线段树+二分+最近公共祖先
AC代码:
/* Author:GavinjouElephant * Title: * Number: * main meanning: * * * */#include <iostream>using namespace std;#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <sstream>#include <cctype>#include <vector>#include <set>#include <cstdlib>#include <map>#include <queue>//#include<initializer_list>//#include <windows.h>//#include <fstream>//#include <conio.h>#define MaxN 0x7fffffff#define MinN -0x7fffffff#define lson 2*k#define rson 2*k+1typedef long long ll;const int INF=0x3f3f3f3f;const int maxn=1e5+10;int Scan()//读入整数外挂.{ int res = 0, ch, flag = 0; if((ch = getchar()) == '-') //判断正负 flag = 1; else if(ch >= '0' && ch <= '9') //得到完整的数 res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9' ) res = res * 10 + ch - '0'; return flag ? -res : res;}void Out(int a) //输出外挂{ if(a>9) Out(a/10); putchar(a%10+'0');}int n,q;class Node{public: int l; int r; int lazy; int c[30];};Node node[4*maxn];int val[maxn];int ancestor[30][maxn];int start[maxn];int end1[maxn];int entry[maxn];int rentry[maxn];int depth[maxn];vector<int>G[maxn];int getAncestor(int a,int dist){ for(int i=20; i>=0; i--) { if(dist & (1<<i)) { a=ancestor[i][a]; } } return a;}void pushup(int k){ for (int i = 0; i < 30; i++) { node[k].c[i] = node[lson].c[i] + node[rson].c[i]; }}void pushdown(int k){ if(node[k].lazy) { for(int i=0; i<30; i++) { if(node[k].lazy & (1<<i) ) { node[lson].c[i]=(node[lson].r-node[lson].l+1)-node[lson].c[i]; node[rson].c[i]=(node[rson].r-node[rson].l+1)-node[rson].c[i]; } } node[lson].lazy^=node[k].lazy; node[rson].lazy^=node[k].lazy; } node[k].lazy=0;}void build(int l,int r,int k){ node[k].l=l; node[k].r=r; node[k].lazy=0; if(l==r) { for(int i=0; i<30; i++) { node[k].c[i]=((val[rentry[l]]>>i)&1); } return ; } int mid=(l+r)/2; build(l,mid,lson); build(mid+1,r,rson); pushup(k);}void chang(int l,int r,int k,int v){ if(l<=node[k].l&&node[k].r<=r) { for(int i=0; i<30; i++) { if(v&(1<<i)) { node[k].c[i]=(node[k].r-node[k].l+1)-node[k].c[i]; } } node[k].lazy^=v; return ; } pushdown(k); int mid=(node[k].l+node[k].r)/2; if(l<=mid) chang(l,min(mid,r),lson,v); if(r>mid) chang(max(mid+1,l),r,rson,v); pushup(k);}ll getAns(int l,int r,int k){ ll ans=0; if(l<=node[k].l&&node[k].r<=r) { for(int i=0; i<30; i++) { ans+=(long long) node[k].c[i]<<i; } return ans; } pushdown(k); int mid=(node[k].l+node[k].r)/2; if(l<=mid) ans+=getAns(l,min(mid,r),lson); if(r>mid) ans+=getAns(max(mid+1,l),r,rson); return ans;}void bfs()//求bfs序{ queue<int> q; int DEF=1;//时间戳 q.push(1); depth[1]=1; while(!q.empty()) { int s=q.front(); q.pop(); start[depth[s]]=min(start[depth[s]],DEF); end1[depth[s]]=max( end1[depth[s]],DEF); rentry[DEF]=s; entry[s]=DEF++; for(int j=0;j<(G[s].size());j++) { int son=G[s][j]; depth[son]=depth[s]+1; q.push(son); } }}void init(){ for(int i=0; i<=n; i++) G[i].clear(); memset(ancestor,-1,sizeof(ancestor)); memset(start,0x3f,sizeof(start)); memset(end1,0,sizeof(end1)); memset(depth,0,sizeof(depth)); memset(entry,0,sizeof(entry));}int main(){#ifndef ONLINE_JUDGE freopen("coco.txt","r",stdin); freopen("lala.txt","w",stdout);#endif while(scanf("%d%d",&n,&q)!=EOF) { n++; init(); for(int i=2; i<=n; i++) { scanf("%d%d",&ancestor[0][i],&val[i]); ancestor[0][i]++; G[ ancestor[0][i] ].push_back(i); } int li=log2(n)+1; for(int k=0; k+1<li; k++) { for(int v=1; v<=n; v++) { if(ancestor[k][v]<0) ancestor[k+1][v]=-1; else ancestor[k+1][v]=ancestor[k][ancestor[k][v]]; } } bfs(); build(1,n,1); for(int i=0; i<q; i++) { int op,b,c,v; scanf("%d%d%d",&op,&b,&c); if(op==0) { scanf("%d",&v); } b++; int d=c+depth[b]; if (d > n || start[d] == INF) { if (op == 1) { printf("-1\n"); } continue; } int x, y; { int l = start[d], r = end1[d]; int ans = end1[d] + 1; while (l <= r) { int mid = (l + r) >> 1; if (entry[getAncestor(rentry[mid], c)] >= entry[b]) { ans = mid; r = mid - 1; } else { l = mid + 1; } } x = ans; } { int l = start[d], r = end1[d]; int ans = end1[d] + 1; while (l <= r) { int mid = (l + r) >> 1; if (entry[getAncestor(rentry[mid], c)] > entry[b]) { ans = mid; r = mid - 1; } else { l = mid + 1; } } y = ans - 1; } if (y < x) { if (op) { printf("-1\n"); } continue; } if (op == 0) { chang(x,y,1,v); } else { printf("%lld\n", getAns(x,y,1)); } } } return 0;}
- [CSU 1322 ZY‘s new company] 线段树维护BFS序
- CSU 1322 ZY‘s new company(线段树维护bfs序)
- CSU oj 1322: ZZY‘s new company
- 【CSU 1258 维护序列】+ 线段树
- cf-edu#6-E - New Year Tree -dfs序+线段树维护
- CSU 1110线段树
- CSU-1809:Parenthesis 括号匹配问题(线段树维护最小值)
- zoj 3363 线段树维护最大值 Alice's present
- 【HDU3966】Aragorn's Story-树链剖分+线段树区间维护
- New company,New start
- CSU 1532: JuQueen(线段树)
- zy
- zy
- zy
- zy
- zy
- poj 2528 Mayor's posters(扫描线+堆维护||离散化+线段树)
- CSU 1098: Happy watering(线段树)
- 常用的获取宽高方法
- 移动应用界面设计的尺寸设置及规范
- GIT删除存在本地,但在服务端不存在的分支的命令
- 五十道编程小题目 --- 02 找素数(质数)java
- scala学习
- CSU 1322 ZY‘s new company(线段树维护bfs序)
- Mysql Join语法解析与性能分析
- 浅谈 RxAndroid + Retrofit + Databinding
- Xamarin Android Circle ImageView 圆形图片实现
- iOS常用的第三方库
- Unity shader Time.y
- Quartz2D 图像处理
- ios ipv6被拒绝,后台定位被拒绝,免费的终极解决方案,大家齐心协力让天下没有解决不了的ipv6问题!
- root账户远程管理