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 }

 

posted on 2015-05-31 23:32  bai_yan  阅读(351)  评论(0编辑  收藏  举报

导航