bzoj4999 This Problem Is Too Simple!

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

Sample Output

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\n",Query(q[i].x,q[i].y,q[i].v));
92   }
93   return 0;
94 }

 

posted @ 2017-09-27 19:54  wfj_2048  阅读(214)  评论(0编辑  收藏  举报