Description
给您一颗树,每个节点有个初始值。
现在支持以下两种操作:
1. C i x(0<=x<2^31) 表示将i节点的值改为x。
2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。
Input
第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。
下面一行N个整数,表示初始时每个节点的初始值。
接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。
接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。
Output
对于每个Q输出单独一行表示所求的答案。
Sample Input
5 6
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 3 40
C 1 40
Q 2 3 40
Q 4 5 30
C 3 10
Q 4 5 30
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 3 40
C 1 40
Q 2 3 40
Q 4 5 30
C 3 10
Q 4 5 30
Sample Output
0
1
1
0
1
1
0
正解:树链剖分+线段树。
傻逼题,直接对于每一个权值建一棵线段树,然后树剖扣路径即可。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define lb(x) (x & -x) 6 #define N (300010) 7 8 using namespace std; 9 10 struct edge{ int nt,to; }g[N<<1]; 11 struct data{ int op,x,y,v; }q[N]; 12 13 int head[N],top[N],fa[N],son[N],dfn[N],dep[N],sz[N],n,num,cnt; 14 int sum[20*N],ls[20*N],rs[20*N],rt[N],hsh[N],a[N],tot,Sz,Q; 15 char ch[5]; 16 17 il int gi(){ 18 RG int x=0,q=1; RG char ch=getchar(); 19 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 20 if (ch=='-') q=-1,ch=getchar(); 21 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 22 return q*x; 23 } 24 25 il void insert(RG int from,RG int to){ 26 g[++num]=(edge){head[from],to},head[from]=num; return; 27 } 28 29 il void dfs1(RG int x,RG int p){ 30 fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v; 31 for (RG int i=head[x];i;i=g[i].nt){ 32 v=g[i].to; if (v==p) continue; 33 dfs1(v,x),sz[x]+=sz[v]; 34 if (sz[son[x]]<=sz[v]) son[x]=v; 35 } 36 return; 37 } 38 39 il void dfs2(RG int x,RG int p,RG int anc){ 40 top[x]=anc,dfn[x]=++cnt; RG int v; 41 if (son[x]) dfs2(son[x],x,anc); 42 for (RG int i=head[x];i;i=g[i].nt){ 43 v=g[i].to; if (v==p || v==son[x]) continue; 44 dfs2(v,x,v); 45 } 46 return; 47 } 48 49 il void update(RG int &x,RG int l,RG int r,RG int p,RG int v){ 50 if (!x) x=++Sz; if (l==r){ sum[x]+=v; return; } RG int mid=(l+r)>>1; 51 p<=mid ? update(ls[x],l,mid,p,v) : update(rs[x],mid+1,r,p,v); 52 sum[x]=sum[ls[x]]+sum[rs[x]]; return; 53 } 54 55 il int query(RG int x,RG int l,RG int r,RG int xl,RG int xr){ 56 if (xl<=l && r<=xr) return sum[x]; RG int mid=(l+r)>>1; 57 if (xr<=mid) return query(ls[x],l,mid,xl,xr); 58 else if (xl>mid) return query(rs[x],mid+1,r,xl,xr); 59 else return query(ls[x],l,mid,xl,mid)+query(rs[x],mid+1,r,mid+1,xr); 60 } 61 62 il int Query(RG int u,RG int v,RG int k){ 63 RG int ans=0; 64 while (top[u]!=top[v]){ 65 if (dep[top[u]]<dep[top[v]]) swap(u,v); 66 ans+=query(rt[k],1,n,dfn[top[u]],dfn[u]),u=fa[top[u]]; 67 } 68 if (dep[u]>dep[v]) swap(u,v); 69 ans+=query(rt[k],1,n,dfn[u],dfn[v]); return ans; 70 } 71 72 int main(){ 73 #ifndef ONLINE_JUDGE 74 freopen("simple.in","r",stdin); 75 freopen("simple.out","w",stdout); 76 #endif 77 n=gi(),Q=gi(); 78 for (RG int i=1;i<=n;++i) a[i]=gi(),hsh[++tot]=a[i]; 79 for (RG int i=1,x,y;i<n;++i) x=gi(),y=gi(),insert(x,y),insert(y,x); 80 dfs1(1,0),dfs2(1,0,1); 81 for (RG int i=1;i<=Q;++i){ 82 scanf("%s",ch); 83 if (ch[0]=='C') q[i].op=1,q[i].x=gi(); else q[i].x=gi(),q[i].y=gi(); 84 q[i].v=gi(),hsh[++tot]=q[i].v; 85 } 86 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 87 for (RG int i=1;i<=n;++i) a[i]=lower_bound(hsh+1,hsh+tot+1,a[i])-hsh,update(rt[a[i]],1,n,dfn[i],1); 88 for (RG int i=1;i<=Q;++i){ 89 q[i].v=lower_bound(hsh+1,hsh+tot+1,q[i].v)-hsh; 90 if (q[i].op) update(rt[a[q[i].x]],1,n,dfn[q[i].x],-1),update(rt[a[q[i].x]=q[i].v],1,n,dfn[q[i].x],1); 91 else printf("%d ",Query(q[i].x,q[i].y,q[i].v)); 92 } 93 return 0; 94 }