HDU3974 Assign the task
题目链接:https://vjudge.net/problem/HDU-3974
知识点: 线段树、DFS
题目大意:
公司中有\(N\)个职员,一个职员对应一个上司,这\(N\)个职员刚好组成一棵树。当给一个职员\(x\)分配任务\(y\)时(即 \(T\) \(x\) \(y\)),\(x\)及其下属及其下属的下属都会放下手头的工作去完成任务\(y\)。对于每次询问(即\(C\) \(x\)),程序输出职员\(x\)正在进行什么任务。
解题思路:
先将公司中职员之间的关系抽象成一棵树,每次分配任务其实就是更新一棵子树。当我们按\(DFS\)遍历的顺序为一棵子树编号时,我们会发现它们是连续的一串数字。于是我们可以先给整棵树用\(DFS\)序编号。每次更新任务其实就是更新一串连续数字对应的职员的当前任务,这就可以用线段树来处理了;而查询职员的当前任务其实就是线段树的单点查询。
AC代码:
1 #include <cstdio> 2 #include <vector> 3 4 using namespace std; 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 8 const int maxn = 50005; 9 vector<int> son[maxn]; 10 bool root[maxn]; 11 int cnt; 12 int lef[maxn],rit[maxn]; 13 int now[maxn<<2]; 14 bool lazy[maxn<<2]; 15 16 void dfs(int rt){ 17 cnt++; 18 lef[rt]=cnt; 19 for(int i=0;i<son[rt].size();i++) 20 dfs(son[rt][i]); 21 rit[rt]=cnt; 22 } 23 void pushdown(int rt){ 24 now[rt<<1]=now[rt<<1|1]=now[rt]; 25 lazy[rt<<1]=lazy[rt<<1|1]=true; 26 lazy[rt]=false; 27 } 28 void build(int l,int r,int rt){ 29 now[rt]=-1; 30 lazy[rt]=false; 31 if(r==l) return; 32 int m=(l+r)>>1; 33 build(lson); 34 build(rson); 35 } 36 void update(int L,int R,int c,int l,int r,int rt){ 37 if(l!=r&&lazy[rt]) pushdown(rt); 38 if(L==l&&R==r){ 39 now[rt]=c; 40 lazy[rt]=true; 41 return; 42 } 43 int m=(l+r)>>1; 44 if(m>=L) update(L,min(m,R),c,lson); 45 if(m<R) update(max(L,m+1),R,c,rson); 46 } 47 int query(int pos,int l,int r,int rt){ 48 if(l!=r&&lazy[rt]) pushdown(rt); 49 if(l==r) return now[rt]; 50 int m=(l+r)>>1; 51 if(m>=pos) return query(pos,lson); 52 else return query(pos,rson); 53 } 54 int main() 55 { 56 int T,N,M,x,y,u,v; 57 scanf("%d",&T); 58 for(int t=1;t<=T;t++){ 59 printf("Case #%d:\n",t); 60 scanf("%d",&N); 61 for(int i=1;i<=N;i++){ 62 root[i]=true; 63 son[i].clear(); 64 } 65 for(int i=1;i<N;i++){ 66 scanf("%d%d",&u,&v); 67 son[v].push_back(u); 68 root[u]=false; 69 } 70 cnt=0; 71 for(int i=1;i<=N;i++){ 72 if(root[i]){ 73 dfs(i); 74 break; 75 } 76 } 77 build(1,cnt+1,1); 78 79 scanf("%d",&M); 80 char ord[5]; 81 for(int i=0;i<M;i++){ 82 scanf("%s",ord); 83 if(ord[0]=='C'){ 84 scanf("%d",&x); 85 printf("%d\n",query(lef[x],1,cnt+1,1)); 86 } 87 else{ 88 scanf("%d%d",&x,&y); 89 update(lef[x],rit[x],y,1,cnt+1,1); 90 } 91 } 92 } 93 return 0; 94 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”