HDU 3974 Assign the task (线段树)

来源:互联网 发布:mariadb mysql 哪个 编辑:程序博客网 时间:2024/06/06 00:48

修改一个点,实际上等价于同时修改一些点。而将一棵树深度遍历所得到的序列中,根节点相同的节点的标号刚好是相邻的。

根据这个性质,用dfs对每个节点重新编号,修改一个点就变成了修改一个连续的区间。本题就变成了区间修改单点查询的线段树问题。


代码:

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;#include <vector>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1int a[50005*4];int add[50005*4];bool root[50005];int N,M;int st[50005];int ed[50005];int Hs[50005];int Num=0;vector<int> G[50005];void dfs(int u){Num++;Hs[u]=Num;st[u]=Num;for(int i=0;i<G[u].size();i++){dfs(G[u][i]);}ed[u]=Num;}void pushdown(int rt){if(add[rt]!=-1){add[rt<<1]=add[rt];add[rt<<1|1]=add[rt];a[rt<<1]=a[rt<<1|1]=add[rt];add[rt]=-1;}}void update(int L,int R,int l,int r,int rt,int n){pushdown(rt);if(L<=l&&R>=r){add[rt]=n;a[rt]=n;return ;}int mid=(l+r)>>1;if(mid>=L) update(L,R,lson,n);if(mid<R) update(L,R,rson,n);}int query(int n,int l,int r,int rt){pushdown(rt);if(l==r){return a[rt];}int mid=(l+r)>>1;if(mid>=n) return query(n,lson);else return query(n,rson);}int main(){int T;int kase=1;scanf("%d",&T);while(T--){memset(a,-1,sizeof(a));memset(add,-1,sizeof(add));memset(root,0,sizeof(root));memset(Hs,0,sizeof(Hs));Num=0;scanf("%d",&N);for(int i=0;i<=N;i++){G[i].clear();}for(int i=0;i<N-1;i++){int u,v;scanf("%d%d",&u,&v);G[v].push_back(u);root[u]=1;}for(int i=1;i<=N;i++){if(!root[i]){dfs(i);break;}}scanf("%d",&M);printf("Case #%d:\n",kase++);for(int i=0;i<M;i++){char ist[2];int x,y;scanf("%s",ist);if(ist[0]=='C'){scanf("%d",&x);printf("%d\n",query(Hs[x],1,Num,1));}else{scanf("%d%d",&x,&y);update(st[x],ed[x],1,Num,1,y);}}}return 0;}

0 0
原创粉丝点击