题目:一颗树,单边修改,链上查询。。实际上链是根到结点的链。网上好像有其他做法,我的想法是这样的:
先不看修改,毫无疑问查询只是查询结点的深度;而修改一条边会有什么影响:影响是且只是以边上深度最深结点为根的子树。
所以就是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 }