[BZOJ 4999]This Problem Is Too Simple!
题目
给您一颗树,每个节点有个初始值。现在支持以下两种操作: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 30OUTPUT
0
1
1
0
解题报告
树剖+权值线段树动态开点+离散
随便搞搞就行了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<map> 5 using namespace std; 6 inline int read(){ 7 int sum(0); 8 char ch(getchar()); 9 for(;ch<'0'||ch>'9';ch=getchar()); 10 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 11 return sum; 12 } 13 struct edge{ 14 int e; 15 edge *n; 16 }ed[200005],*pre[100005]; 17 int tot; 18 inline void insert(int s,int e){ 19 ed[++tot].e=e; 20 ed[tot].n=pre[s]; 21 pre[s]=&ed[tot]; 22 } 23 map<int,int>ma; 24 int num; 25 int n,q; 26 int a[100005]; 27 int dep[100005],size[100005],fa[100005],son[100005]; 28 inline void dfs1(int u){ 29 size[u]=1; 30 son[u]=0; 31 for(edge *i=pre[u];i;i=i->n){ 32 int e(i->e); 33 if(e!=fa[u]){ 34 fa[e]=u; 35 dep[e]=dep[u]+1; 36 dfs1(e); 37 size[u]+=size[e]; 38 if(size[e]>size[son[u]]) 39 son[u]=e; 40 } 41 } 42 } 43 int timee; 44 int id[100005],pos[100005],top[100005]; 45 inline void dfs2(int u,int rt){ 46 top[u]=rt; 47 id[u]=++timee; 48 pos[timee]=u; 49 if(son[u]) 50 dfs2(son[u],rt); 51 for(edge *i=pre[u];i;i=i->n){ 52 int e(i->e); 53 if(e!=fa[u]&&e!=son[u]) 54 dfs2(e,e); 55 } 56 } 57 int cnt; 58 int rt[300005],lch[12000005],rch[12000005],sum[12000005]; 59 inline void update(int &x,int pos,int w,int l,int r){ 60 if(!x) 61 x=++cnt; 62 sum[x]+=w; 63 if(l==r) 64 return; 65 int mid((l+r)>>1); 66 if(pos<=mid) 67 update(lch[x],pos,w,l,mid); 68 else 69 update(rch[x],pos,w,mid+1,r); 70 } 71 inline int query(int x,int ll,int rr,int l,int r){ 72 if(!x) 73 return 0; 74 if(ll<=l&&r<=rr) 75 return sum[x]; 76 int mid((l+r)>>1),ret(0); 77 if(ll<=mid) 78 ret+=query(lch[x],ll,rr,l,mid); 79 if(mid<rr) 80 ret+=query(rch[x],ll,rr,mid+1,r); 81 return ret; 82 } 83 inline int ask(int x,int y,int z){ 84 int ret(0),tmp(ma[z]); 85 while(top[x]^top[y]){ 86 if(dep[top[x]]<dep[top[y]]) 87 swap(x,y); 88 ret+=query(rt[tmp],id[top[x]],id[x],1,n); 89 x=fa[top[x]]; 90 } 91 if(dep[x]>dep[y]) 92 swap(x,y); 93 ret+=query(rt[tmp],id[x],id[y],1,n); 94 return ret; 95 } 96 char op[2]; 97 int main(){ 98 memset(pre,NULL,sizeof(pre)); 99 n=read(),q=read(); 100 for(int i=1;i<=n;++i) 101 a[i]=read(); 102 for(int i=1;i<n;++i){ 103 int x(read()),y(read()); 104 insert(x,y),insert(y,x); 105 } 106 dfs1(1); 107 dfs2(1,1); 108 for(int i=1;i<=n;++i){ 109 if(!ma[a[i]]) 110 ma[a[i]]=++num; 111 update(rt[ma[a[i]]],id[i],1,1,n); 112 } 113 while(q--){ 114 scanf("%s",op); 115 if(op[0]=='C'){ 116 int x(read()),y(read()); 117 update(rt[ma[a[x]]],id[x],-1,1,n); 118 if(!ma[y]) 119 ma[y]=++num; 120 a[x]=y; 121 update(rt[ma[y]],id[x],1,1,n); 122 } 123 else{ 124 int x(read()),y(read()),z(read()); 125 if(!ma[z]) 126 puts("0"); 127 else 128 printf("%d\n",ask(x,y,z)); 129 } 130 } 131 }