BZOJ1103 [POI2007]大都市meg(DFS序)

题目:一颗树,单边修改,链上查询。。实际上链是根到结点的链。网上好像有其他做法,我的想法是这样的:

先不看修改,毫无疑问查询只是查询结点的深度;而修改一条边会有什么影响:影响是且只是以边上深度最深结点为根的子树。

所以就是DFS序了。把子树转化为区间,然后用区间修改、单点查询的线段树维护。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXN 255555
 6 struct Edge{
 7     int v,nxt;
 8 }edge[MAXN]; 
 9 int n,NE,head[MAXN];
10 void addEdge(int u,int v){
11     edge[NE].v=v; edge[NE].nxt=head[u]; head[u]=NE++;
12 }
13 
14 int dep[MAXN],l[MAXN],r[MAXN],stack[MAXN],odr;
15 void dfs(){
16     int top=0;
17     stack[++top]=1;
18     while(top){
19         int u=stack[top];
20         if(l[u]){
21             r[u]=odr; --top;
22             continue; 
23         }
24         l[u]=++odr;
25         for(int i=head[u]; i!=-1; i=edge[i].nxt){
26             int v=edge[i].v;
27             stack[++top]=v;
28             dep[v]=dep[u]+1;
29         }
30     }
31 }
32 
33 int tree[MAXN<<2],N,x,y;
34 void update(int i,int j,int k){
35     if(x<=i&&j<=y){
36         ++tree[k];
37         return;
38     }
39     if(tree[k]){
40         tree[k<<1]+=tree[k]; tree[k<<1|1]+=tree[k];
41         tree[k]=0;
42     }
43     int mid=i+j>>1;
44     if(x<=mid) update(i,mid,k<<1);
45     if(y>mid) update(mid+1,j,k<<1|1);
46 }
47 int query(int i,int j,int k){
48     if(i==j) return tree[k];
49     if(tree[k]){
50         tree[k<<1]+=tree[k]; tree[k<<1|1]+=tree[k];
51         tree[k]=0;
52     }
53     int mid=i+j>>1;
54     if(x<=mid) return query(i,mid,k<<1);
55     return query(mid+1,j,k<<1|1);
56 }
57 
58 int main(){
59     int m,a,b;
60     char op[11];
61     memset(head,-1,sizeof(head));
62     scanf("%d",&n);
63     for(int i=1; i<n; ++i){
64         scanf("%d%d",&a,&b);
65         if(a>b) swap(a,b);
66         addEdge(a,b);
67     }
68     dfs();
69     for(N=1; N<odr; N<<=1);
70     scanf("%d",&m);
71     m+=n-1;
72     while(m--){
73         scanf("%s",op);
74         if(op[0]=='W'){
75             scanf("%d",&a);
76             x=l[a];
77             printf("%d\n",dep[a]-query(1,N,1));
78         }else{
79             scanf("%d%d",&a,&b);
80             if(a<b) a=b;
81             x=l[a]; y=r[a];
82             update(1,N,1);
83         }
84     }
85     return 0;
86 }

 

转载于:https://www.cnblogs.com/WABoss/p/4873944.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值