kb-07线段树--10--dfs序建树
1 /* 2 hdu3974 3 dfs序建树,然后区间修改查询; 4 */ 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<algorithm> 9 #define MAX_N 50005 10 using namespace std; 11 12 int N,M; 13 struct Node 14 { 15 int to,next; 16 }edge[MAX_N]; 17 struct TREE 18 {//val记录的是区间; 19 int l,r,val,lazy; 20 }tr[MAX_N*4]; 21 int head[MAX_N],cnt,tot; 22 int Start[MAX_N],End[MAX_N]; 23 24 void Addedge(int u,int v)//链式前向星存图; 25 { 26 //tot是边的编号; 27 edge[tot].to=u;//以v为起点的边;终点是u; 28 edge[tot].next=head[v];//这条边的下一条边是几号边,依然是v为起点的边; 29 head[v]=tot++;//更新v为起点的边的入口; 30 } 31 void dfs(int x) 32 { 33 cnt++;//初始为0;这里是1了,从1开始编号; 34 Start[x]=cnt;//起点是x的编号 35 for(int i=head[x];i!=-1;i=edge[i].next)//遍历以v为起点的边; 36 { 37 dfs(edge[i].to); 38 } 39 End[x]=cnt;//遍历完子树后可以得到这个树根的编号范围就是star&end; 40 //dfs先根遍历,把x为根的子树的所有的节点编号在一段区间内,连续编号,并且记录该区间的编号起始和结束,当线段树修改值的时候就直接修改该区间; 41 } 42 void build(int rt,int l,int r) 43 { 44 tr[rt].l=l; 45 tr[rt].r=r; 46 tr[rt].val=-1; 47 tr[rt].lazy=0; 48 if(l==r) 49 return; 50 int mid=(l+r)/2; 51 build(rt<<1,l,mid); 52 build(rt<<1|1,mid+1,r); 53 } 54 void Pushdown(int rt) 55 { 56 int ls=rt<<1,rs=rt<<1|1; 57 if(tr[rt].lazy) 58 { 59 tr[rs].val=tr[ls].val=tr[rt].val; 60 tr[rs].lazy=tr[ls].lazy=1; 61 tr[rt].lazy=0; 62 } 63 } 64 void Update(int rt,int l,int r,int x) 65 { 66 if(tr[rt].l==l&&tr[rt].r==r) 67 { 68 tr[rt].val=x; 69 tr[rt].lazy=1; 70 return ; 71 } 72 Pushdown(rt); 73 int ls=rt<<1,rs=rt<<1|1; 74 if(l<=tr[ls].r) 75 { 76 if(r<=tr[ls].r) 77 Update(ls,l,r,x); 78 else 79 Update(ls,l,tr[ls].r,x); 80 } 81 if(r>=tr[rs].l) 82 { 83 if(l>=tr[rs].l) 84 Update(rs,l,r,x); 85 else 86 Update(rs,tr[rs].l,r,x); 87 } 88 } 89 int Query(int rt,int a) 90 { 91 if(tr[rt].l==a&&tr[rt].r==a) 92 { 93 return tr[rt].val; 94 } 95 Pushdown(rt); 96 int mid=(tr[rt].l+tr[rt].r)/2; 97 if(a<=mid) 98 return Query(rt<<1,a); 99 else 100 return Query(rt<<1|1,a); 101 } 102 int main() 103 { 104 int T,k=1; 105 cin>>T; 106 while(T--) 107 { 108 printf("Case #%d:\n",k++); 109 cnt=0; 110 tot=0; 111 memset(edge,0,sizeof(edge)); 112 memset(head,-1,sizeof(head)); 113 memset(Start,-1,sizeof(Start)); 114 memset(End,-1,sizeof(End)); 115 bool used[MAX_N]; 116 memset(used,false,sizeof(used)); 117 cin>>N; 118 for(int i=0;i<N-1;i++) 119 { 120 int u,v; 121 cin>>u>>v;//v是u的上级; 122 used[u]=true ;//表示u是有上级的,也就是有入度的; 123 Addedge(u,v); 124 } 125 for(int i=1;i<=N;i++) 126 { 127 if(!used[i])//找到入度为0的点,就是整个树的入口; 128 { 129 dfs(i); 130 break; 131 } 132 } 133 build(1,1,N); 134 cin>>M; 135 for(int i=0;i<M;i++) 136 { 137 char a[10]; 138 scanf("%s",a); 139 if(a[0]=='C') 140 { 141 int x; 142 cin>>x; 143 int ans=Query(1,Start[x]);//该点的编号就是起点的编号; 144 cout<<ans<<endl; 145 } 146 else 147 { 148 int a,b; 149 cin>>a>>b; 150 Update(1,Start[a],End[a],b); 151 } 152 } 153 154 } 155 return 0; 156 }