S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。
对每个QS和QM事件,输出一行,表示旅行者记下的数字。
N,Q < =10^5 , C < =10^5
数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
C<=10^5,极限状况下线段树最多需要添加log(10^5)/log(2) * n == 160w个结点,题目时限20s,512m内存,似乎可以用线段树强行搞。
1 #include<algorithm>
2 #include<cstring>
3 #include<cmath>
4 #include<cstdio>
5 using namespace std;
6 const int mxn=100010;
7 int read(){
8 int x=0,f=1;char ch=getchar();
9 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
10 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
11 return x*f;
12 }
13 struct edge{int v,nxt;}e[mxn<<1];
14 int hd[mxn],mct=0;
15 void add_edge(int u,int v){e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;}
16 int n,Q;
17 struct node{
18 int top,fa;
19 int w,e;
20 int size,son;
21 }t[mxn];
22 int dep[mxn];
23 struct sgt{
24 int lc,rc;
25 int mx,smm;
26 }st[mxn<<4];
27 int sz=0;
28 int rt[mxn];//每种颜色对应的线段树根
29 int w[mxn],c[mxn];
30 void DFS1(int u,int fa){
31 t[u].fa=fa;
32 t[u].size=1;
33 dep[u]=dep[fa]+1;
34 for(int i=hd[u];i;i=e[i].nxt){
35 int v=e[i].v;
36 if(v==fa)continue;
37 DFS1(v,u);
38 t[u].size+=t[v].size;
39 if(t[v].size>t[t[u].son].size)
40 t[u].son=v;
41 }
42 return;
43 }
44 void DFS2(int u,int top){
45 t[u].w=++sz;
46 t[u].top=top;
47 if(t[u].son)DFS2(t[u].son,top);
48 for(int i=hd[u];i;i=e[i].nxt){
49 int v=e[i].v;
50 if(v!=t[u].son && v!=t[u].fa)DFS2(v,v);
51 }
52 t[u].e=sz;
53 return;
54 }
55 void pushup(int rt){
56 int lc=st[rt].lc;int rc=st[rt].rc;
57 st[rt].mx=max(st[lc].mx,st[rc].mx);
58 st[rt].smm=st[lc].smm+st[rc].smm;
59 // printf("pushup:rt:%d data:%d\n",rt,st[rt].smm);
60 return;
61 }
62 void update(int p,int v,int l,int r,int &rt){
63 if(!rt){rt=++sz;}
64 if(l==r){st[rt].mx=st[rt].smm=v;return;}
65 int mid=(l+r)>>1;
66 if(p<=mid)update(p,v,l,mid,st[rt].lc);
67 else update(p,v,mid+1,r,st[rt].rc);
68 pushup(rt);
69 return;
70 }
71 int qsum(int L,int R,int l,int r,int rt){
72 // printf("%d %d %d %d %d :%d\n",L,R,l,r,rt,st[rt].smm);
73 if(!rt)return 0;
74 if(L<=l && r<=R){return st[rt].smm;}
75 int mid=(l+r)>>1;
76 int res=0;
77 if(L<=mid)res+=qsum(L,R,l,mid,st[rt].lc);
78 if(R>mid)res+=qsum(L,R,mid+1,r,st[rt].rc);
79 return res;
80 }
81 int qmax(int L,int R,int l,int r,int rt){
82 if(!rt)return -1e9;
83 if(L<=l && r<=R){return st[rt].mx;}
84 int mid=(l+r)>>1;
85 int res=-1e9;
86 if(L<=mid)res=max(res,qmax(L,R,l,mid,st[rt].lc));
87 if(R>mid)res=max(res,qmax(L,R,mid+1,r,st[rt].rc));
88 return res;
89 }
90 int asksum(int color,int x,int y){
91 int res=0;
92 while(t[x].top!=t[y].top){
93 if(dep[t[x].top]<dep[t[y].top])swap(x,y);
94 res+=qsum(t[t[x].top].w,t[x].w,1,n,rt[color]);
95 x=t[t[x].top].fa;
96 }
97 if(dep[x]>dep[y])swap(x,y);
98 res+=qsum(t[x].w,t[y].w,1,n,rt[color]);
99 return res;
100 }
101 int askmax(int color,int x,int y){
102 int res=-1e9;
103 while(t[x].top!=t[y].top){
104 if(dep[t[x].top]<dep[t[y].top])swap(x,y);
105 res=max(res,qmax(t[t[x].top].w,t[x].w,1,n,rt[color]));
106 x=t[t[x].top].fa;
107 }
108 if(dep[x]>dep[y])swap(x,y);
109 res=max(res,qmax(t[x].w,t[y].w,1,n,rt[color]));
110 return res;
111 }
112 int main()
113 {
114 int i,j,u,v;
115 n=read();Q=read();
116 for(i=1;i<=n;i++){w[i]=read();c[i]=read();}
117 for(i=1;i<n;i++){
118 u=read();v=read();
119 add_edge(u,v);
120 add_edge(v,u);
121 }
122 DFS1(n/2,0);
123 DFS2(n/2,n/2);
124 for(i=1;i<=n;i++){
125 update(t[i].w,w[i],1,n,rt[c[i]]);
126 }
127 char op[5];int x,y;
128 while(Q--){
129 scanf("%s",op);x=read();y=read();
130 if(op[0]==‘C‘){
131 if(op[1]==‘C‘){
132 update(t[x].w,0,1,n,rt[c[x]]);
133 c[x]=y;
134 update(t[x].w,w[x],1,n,rt[c[x]]);
135 }
136 else{
137 update(t[x].w,y,1,n,rt[c[x]]);
138 w[x]=y;
139 }
140 }
141 else{
142 if(op[1]==‘S‘){printf("%d\n",asksum(c[x],x,y));}
143 else{printf("%d\n",askmax(c[x],x,y));}
144 }
145 }
146 return 0;
147 }