传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3531
考场上爆零,发奋学链剖,然后水过……
感谢GreenClouds神犇教我的动态开点的线段树
递归的链剖会在链的时候爆栈,蒟蒻YY了一个非递归的,见代码
Code:
#include<cstdio>
#include<stack>
#include<deque>
#include<vector>
#include<iostream>
#include<algorithm>
#define X first
#define Y second
using namespace std;
const int maxn=100100;
vector<int>G[maxn];
typedef pair<int,int> pii;
void add(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
int top[maxn],w[maxn],fa[maxn],son[maxn],siz[maxn],dep[maxn],z=0;
int n,q;
int W[maxn],C[maxn];
//递归版
/*
void dfs(const int &u){
son[u]=0;siz[u]=1;
for(int i=0;i<G[u].size();i++){
const int &v=G[u][i];
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dfs(v);
if(siz[son[u]]<siz[v])son[u]=v;
siz[u]+=siz[v];
}
}
}*/
//GTY神犇版
/*
inline void dfs(int root,int BigBoss)
{
memset(cur,-1,sizeof(cur));
int now=root;
while (now!=f[root])
{
if (cur[now]==-1)
{
cur[now]=point[now];
boss[now]=BigBoss;
bossson[BigBoss]++;
NewSon(now);
}
else cur[now]=next[cur[now]];
if (cur[now]&&v[cur[now]]==f[now]) cur[now]=next[cur[now]];
if (!cur[now])
{
now=f[now];
continue;
}
f[v[cur[now]]]=now;
now=v[cur[now]];
}
}*/
//YY的非递归#1
int order[maxn];
stack<int>S;
void dfs(int u){
S.push(u);
order[0]=0;
while(!S.empty()){
int u=S.top();S.pop();
son[u]=0;siz[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=fa[u]){
dep[v]=dep[u]+1;
fa[v]=u;
S.push(v);
order[++order[0]]=v;
}
}
}
for(int i=order[0];i>=1;i--){
int u=order[i];
if(siz[son[fa[u]]]<siz[u])son[fa[u]]=u;
siz[fa[u]]+=siz[u];
}
}
//递归版
/*
void build(int u,int tp){
w[u]=++z;top[u]=tp;
if(son[u])build(son[u],tp);
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=fa[u]&&v!=son[u])build(v,v);
}
}*/
//YY的非递归#2
deque<pii>Q;
void build(int u,int tp){
Q.push_front(pii(u,tp));
while(!Q.empty()){
pii t=Q.front();Q.pop_front();
int u=t.X,tp=t.Y;
w[u]=++z;top[u]=tp;
if(son[u])Q.push_front(pii(son[u],tp));
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=fa[u]&&v!=son[u])
Q.push_back(pii(v,v));
}
}
}
int V=0;
struct seg_tree{
struct node{
int l,r,sum,m;
node(){l=0;r=0;sum=0;m=0;}
};
node t[3010000];
void rz(int x){
t[x].sum=t[t[x].l].sum+t[t[x].r].sum;
t[x].m=max(t[t[x].l].m,t[t[x].r].m);
}
void change(int l,int r,int pos,int val,int &c){
if(l>r)return;
if(!c)c=++V;
if(l==r){
t[c].sum=t[c].m=val;
return;
}int mid=l+r>>1;
if(pos<=mid)change(l,mid,pos,val,t[c].l);
else change(mid+1,r,pos,val,t[c].r);
rz(c);
}
int qsum(int l,int r,int l0,int r0,int &c){
if(c==0)return 0;
if(l>r)return 0;
if(l0<=l&&r0>=r)
return t[c].sum;
int mid=l+r>>1;
int ans=0;
if(l0<=mid)ans+=qsum(l,mid,l0,r0,t[c].l);
if(r0>mid) ans+=qsum(mid+1,r,l0,r0,t[c].r);
return ans;
}
int qmax(int l,int r,int l0,int r0,int &c){
if(c==0)return 0;
if(l>r)return 0;
if(l0<=l&&r0>=r)
return t[c].m;
int mid=l+r>>1;
int ans=0;
if(l0<=mid)ans=max(ans,qmax(l,mid,l0,r0,t[c].l));
if(r0>mid) ans=max(ans,qmax(mid+1,r,l0,r0,t[c].r));
return ans;
}
}T;
int Tr[maxn];
void CC(int x,int c){
T.change(1,n,w[x],0,Tr[C[x]]);
C[x]=c;
T.change(1,n,w[x],W[x],Tr[C[x]]);
}
void CW(int x,int ww){
W[x]=ww;
T.change(1,n,w[x],ww,Tr[C[x]]);
}
int QS(int u,int v){
int ans=0;int c=C[u];
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
int a=w[u],b=w[top[u]];
if(a>b)swap(a,b);
ans+=T.qsum(1,n,a,b,Tr[c]);
u=fa[top[u]];
}else{
int a=w[v],b=w[top[v]];
if(a>b)swap(a,b);
ans+=T.qsum(1,n,a,b,Tr[c]);
v=fa[top[v]];
}
}
int a=w[u],b=w[v];
if(a>b)swap(a,b);
ans+=T.qsum(1,n,a,b,Tr[c]);
return ans;
}
int QM(int u,int v){
int ans=0;int c=C[u];
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
int a=w[u],b=w[top[u]];
if(a>b)swap(a,b);
ans=max(ans,T.qmax(1,n,a,b,Tr[c]));
u=fa[top[u]];
}else{
int a=w[v],b=w[top[v]];
if(a>b)swap(a,b);
ans=max(ans,T.qmax(1,n,a,b,Tr[c]));
v=fa[top[v]];
}
}
int a=w[u],b=w[v];
if(a>b)swap(a,b);
ans=max(ans,T.qmax(1,n,a,b,Tr[c]));
return ans;
}
int main(){
// freopen("Q3.in","r",stdin);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d%d",&W[i],&C[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}dfs(1);build(1,1);
for(int i=1;i<=n;i++){
CC(i,C[i]);
CW(i,W[i]);
}
while(q--){
int x,y,c,w;
char opt[2];
scanf("%s",opt);
if(opt[0]=='C'&&opt[1]=='C'){
scanf("%d%d",&x,&c);
CC(x,c);
}else
if(opt[0]=='C'&&opt[1]=='W'){
scanf("%d%d",&x,&w);
CW(x,w);
}else
if(opt[0]=='Q'&&opt[1]=='S'){
scanf("%d%d",&x,&y);
printf("%d\n",QS(x,y));
}else
if(opt[0]=='Q'&&opt[1]=='M'){
scanf("%d%d",&x,&y);
printf("%d\n",QM(x,y));
}
}
return 0;
}