其实还是比较好做的,树链剖分现在越来越熟练了。对于这道题来说,所有的部落一开始全部在停战状态,所以它们的边权先初始赋为0,对于一个开战操作,就把链接这两个点的边上的边权赋一个大于0的数,查询时若是有和大于0的时候,我们便认为不能走。如果U停战操作,我们在C的时候要注意保存每一次开战的顺序,开展的村庄编号,停战的时候便将它们之间的边权赋为0。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+7; 4 const int INF=0x3f3f3f3f; 5 struct node{ 6 int nxt,to,val; 7 }edge[maxn*3]; 8 struct node1{ 9 int l,r,sum,lazy; 10 }tree[maxn*4]; 11 struct node2{ 12 int u,v; 13 }st[maxn*2]; 14 int head[maxn],cnt; 15 void add(int x,int y){ 16 edge[++cnt].nxt=head[x]; 17 edge[cnt].to=y; 18 edge[cnt].val=0; 19 head[x]=cnt; 20 } 21 int n,m,kkk,x,y; 22 int q1,q2; 23 int ljb; 24 char opt[666]; 25 int dep[maxn],son[maxn],fa[maxn],size[maxn],dfn[maxn],top[maxn],va[maxn],w[maxn],Time; 26 void dfs1(int x,int f){ 27 size[x]=1; 28 fa[x]=f; 29 dep[x]=dep[f]+1; 30 int maxson=-1; 31 for(int i=head[x];i;i=edge[i].nxt){ 32 int go=edge[i].to; 33 if(go==fa[x]) continue; 34 w[go]=edge[i].val; 35 dfs1(go,x); 36 if(size[go]>maxson){ 37 maxson=size[go]; 38 son[x]=go; 39 } 40 } 41 } 42 void dfs2(int x,int topf){ 43 top[x]=topf; 44 dfn[x]=++Time; 45 va[dfn[x]]=w[x]; 46 if(!son[x]) return; 47 dfs2(son[x],topf); 48 for(int i=head[x];i;i=edge[i].nxt){ 49 int go=edge[i].to; 50 if(go==fa[x]||go==son[x]) continue; 51 dfs2(go,go); 52 } 53 } 54 void build(int now,int l,int r){ 55 tree[now].l=l,tree[now].r=r,tree[now].lazy=-1; 56 if(l==r){ 57 tree[now].sum=va[l]; 58 return; 59 } 60 int mid=(l+r)>>1; 61 build(now<<1,l,mid); 62 build(now<<1|1,mid+1,r); 63 tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; 64 } 65 void pushdown(int now){ 66 if(tree[now].lazy!=-1){ 67 tree[now<<1].sum=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].lazy; 68 tree[now<<1|1].sum=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].lazy; 69 tree[now<<1].lazy=tree[now].lazy; 70 tree[now<<1|1].lazy=tree[now].lazy; 71 tree[now].lazy=-1; 72 } 73 } 74 void update(int now,int l,int r,int v){ 75 if(tree[now].l>=l&&tree[now].r<=r){ 76 tree[now].sum=(tree[now].r-tree[now].l+1)*v; 77 tree[now].lazy=v; 78 return; 79 } 80 pushdown(now); 81 int mid=(tree[now].l+tree[now].r)>>1; 82 if(l<=mid) update(now<<1,l,r,v); 83 if(r>mid) update(now<<1|1,l,r,v); 84 tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; 85 } 86 int query(int now,int l,int r){ 87 if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum; 88 pushdown(now); 89 int vak=0; 90 int mid=(tree[now].l+tree[now].r)>>1; 91 if(l<=mid) vak+=query(now<<1,l,r); 92 if(r>mid) vak+=query(now<<1|1,l,r); 93 return vak; 94 } 95 int link(int u,int v){ 96 if(u==v) return 0; 97 int ans=0; 98 while(top[u]!=top[v]){ 99 if(dep[top[u]]<dep[top[v]]) swap(u,v); 100 ans+=query(1,dfn[top[u]],dfn[u]); 101 u=fa[top[u]]; 102 } 103 if(dep[u]<dep[v]) swap(u,v); 104 ans+=query(1,dfn[v]+1,dfn[u]); 105 return ans; 106 } 107 int main(){ 108 scanf("%d%d",&n,&m); 109 for(int i=1;i<n;i++){ 110 scanf("%d%d",&x,&y); 111 add(x,y);add(y,x); 112 } 113 dfs1(1,0); 114 dfs2(1,1); 115 build(1,1,n); 116 for(int i=1;i<=m;i++){ 117 scanf("%s",opt); 118 if(opt[0]=='Q'){ 119 scanf("%d%d",&q1,&q2); 120 int ans=link(q1,q2); 121 if(ans>0){ 122 printf("No "); 123 } 124 else printf("Yes "); 125 } 126 if(opt[0]=='C'){ 127 scanf("%d%d",&q1,&q2); 128 int who=dep[q1]<dep[q2]?q2:q1; 129 update(1,dfn[who],dfn[who],1); 130 st[++kkk].u=q1; 131 st[kkk].v=q2; 132 } 133 if(opt[0]=='U'){ 134 scanf("%d",&ljb); 135 int who=dep[st[ljb].u]<dep[st[ljb].v]?st[ljb].v:st[ljb].u; 136 update(1,dfn[who],dfn[who],0); 137 } 138 } 139 return 0; 140 }