题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974
1 5 4 3 3 2 1 3 5 2 5 C 3 T 2 1 C 3 T 3 2 C 3
Case #1: -1 1 2
题意:
给出1 到 N 点的上下级关系,如果给 a 分配任务 b,那么他的所有下属。都停下目前手上的工作,开始做任务b 。
给出例如 u , v 表示v 是 u 的上级!
有两个操作:
1:T x y 分配给 x 员工 任务 y ;
2:C x 询问 x 员工的当前任务;
PS:从树的根节点向下遍历并对每个节点 i 按序编号为s[v],当遍历完 i 的所有子节点后最后子节点的编号为e[u] ;
此时点 i 的覆盖区域就是s[ i ]到e[ i ]区间,给点 i 分配任务就相当于对s[ i ],e[ i ] 进行区间更新!
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 #define LL long long const int maxn = 111111; LL add[maxn<<2];//用来标记每个节点,为0则表示没有标记,否则为标记; LL val[maxn<<2];//每个节点的值 LL col[maxn<<2]; int head[maxn], s[maxn], e[maxn], vis[maxn]; int cnt, tot; struct Edge { int to; int next; } edge[maxn]; void init() { cnt = 0; tot = 0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); } void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs(int u) { cnt++; s[u] = cnt; for(int i = head[u]; i != -1; i = edge[i].next) { dfs(edge[i].to); } e[u] = cnt; } void PushDown(int rt)//把当前结点的信息更新给儿子结点 { if(col[rt]) //已经标记过,该区间被改变过 { col[rt<<1] = col[rt] ;//此处是替换,而非“+=” col[rt<<1|1] = col[rt]; val[rt<<1] = col[rt];//此处是替换,而非“+=” val[rt<<1|1] = col [rt]; col[rt] = 0;//将标记向儿子节点移动后,父节点的延迟标记去掉 } } void build(int l,int r,int rt) { col[rt] = 0;//初始化为所有结点未被标记 val[rt] = -1;//初始化每个节点为-1 if (l == r) { //scanf("%d",&val[rt]); return ; } int mid = (l + r) >> 1; build(lson); build(rson); } void update(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { col[rt] = c; val[rt] = c; return ; } /*当要对被延迟标记过的这段区间的儿子节点进行更新时,先要将延迟标记向儿子节点移动 当然,如果一直没有对该段的儿子节点更新,延迟标记就不需要向儿子节点移动,这样就使 更新操作的时间复杂度仍为O(logn),也是使用延迟标记的原因。 */ PushDown(rt);//向下传递 int mid = (l + r) >> 1; if (L <= mid) update(L , R , c , lson);//更新左儿子 if (mid < R) update(L , R , c , rson);//更新右儿子 } LL query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return val[rt]; } //要取rt子节点的值时,也要先把rt的延迟标记向下移动 PushDown(rt); int mid = (l + r) >> 1; LL ret = 0; if (L <= mid) ret = query(L , R , lson); if (mid < R) ret = query(L , R , rson); return ret; } int main() { int N , Q; int T; int cas = 0; scanf("%d",&T); while(T--) { init(); scanf("%d",&N);//N为节点数 int u, v; for(int i = 1; i < N; i++) { scanf("%d%d",&u,&v); addedge(v, u); vis[u] = 1; } for(int i = 1; i <= N; i++) { if(!vis[i]) { dfs(i); break; } } build(1 , N , 1); //建树 scanf("%d",&Q); printf("Case #%d:\n",++cas); while(Q--)//Q为询问次数 { char op[10]; int a , b , c; scanf("%s",op); if(op[0] == 'C') { scanf("%d",&a); printf("%lld\n",query(s[a], s[a], 1, N, 1)); } else { scanf("%d%d",&a,&b); update(s[a], e[a], b, 1, N, 1); } } } return 0; }