被主席树的标签坑的死去活来2333
总是觉得一颗主席树少了一个标记
你需要维护区间+宗教+权值
所以你需要很多棵线段树
动态开点就好了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=2e5;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
struct Front_star{
int u,v,nxt;
}e[N*10];
int cnt=1;
int first[N]={};
void add(int u,int v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
//
int dep[N]={};
int top[N]={};
int fa[N]={};
int son[N]={};
int siz[N]={};
int pre[N]={};
int tree[N]={};
int tot=0;
void dfs1(int x,int fat,int depth){
dep[x]=depth;
fa[x]=fat;
siz[x]=1;
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(v==fat)continue;
dfs1(v,x,depth+1);
siz[x]+=siz[v];
if(!son[x]||siz[son[x]]<siz[v]){
son[x]=v;
}
}
}
void dfs2(int x,int tp){
tree[x]=++tot;
pre[tot]=x;
top[x]=tp;
if(!son[x])return;
dfs2(son[x],tp);
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[x])continue;
if(v==son[x])continue;
dfs2(v,v);
}
}
int root[N]={};
int val[N]={};
int n,Q;
struct Segment_Tree{
int lson,rson,sum,Mx;
}T[N*32];
int Node=0;
inline void PushUp(int x){
T[x].sum=0;
T[x].Mx=0;
if(T[x].lson)T[x].sum=T[T[x].lson].sum,T[x].Mx=T[T[x].lson].Mx;
if(T[x].rson)T[x].sum+=T[T[x].rson].sum,T[x].Mx=max(T[x].Mx,T[T[x].rson].Mx);
}
inline void update(int &x,int l,int r,int val,int pos){
if(!x)x=++Node;
if(l==r){
T[x].sum+=val;
T[x].Mx+=val;
return;
}
int mid=(l+r)/2;
if(pos<=mid)update(T[x].lson,l,mid,val,pos);
else update(T[x].rson,mid+1,r,val,pos);
PushUp(x);
}
inline int querysum(int x,int Ql,int Qr,int l,int r){
if(!x)return 0;
if(Ql<=l&&r<=Qr){
return T[x].sum;
}
int ret=0;
int mid=(l+r)/2;
if(Ql<=mid)ret+=querysum(T[x].lson,Ql,Qr,l,mid);
if(mid< Qr)ret+=querysum(T[x].rson,Ql,Qr,mid+1,r);
return ret;
}
inline int querymax(int x,int Ql,int Qr,int l,int r){
if(!x)return 0;
if(Ql<=l&&r<=Qr){
return T[x].Mx;
}
int ret=-1;
int mid=(l+r)/2;
if(Ql<=mid)ret=max(ret,querymax(T[x].lson,Ql,Qr,l,mid));
if(mid< Qr)ret=max(ret,querymax(T[x].rson,Ql,Qr,mid+1,r));
return ret;
}
inline int Getsum(int x,int y,int c){
int ret=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret+=querysum(root[c],tree[top[x]],tree[x],1,n);
x=fa[top[x]];
}
if(tree[x]>tree[y])swap(x,y);
ret+=querysum(root[c],tree[x],tree[y],1,n);
return ret;
}
inline int Getmax(int x,int y,int c){
int ret=-1;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret=max(ret,querymax(root[c],tree[top[x]],tree[x],1,n));
x=fa[top[x]];
}
if(tree[x]>tree[y])swap(x,y);
ret=max(ret,querymax(root[c],tree[x],tree[y],1,n));
return ret;
}
int Belong[N]={};
int Grade[N]={};
int main(){
// freopen("2952.in","r",stdin);
read(n);
read(Q);
for(int i=1;i<=n;i++)read(Grade[i]),read(Belong[i]);
for(int i=1;i<n;i++){
int u,v;
read(u);
read(v);
add(u,v);
add(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=1;i<=n;i++){
update(root[Belong[i]],1,n,Grade[i],tree[i]);
}
while(Q--){
char opt[3];
scanf("%s",opt);
int x,y;
read(x);
read(y);
if(opt[1]=='C'){
update(root[Belong[x]],1,n,-Grade[x],tree[x]);
Belong[x]=y;
update(root[Belong[x]],1,n,Grade[x], tree[x]);
}
if(opt[1]=='W'){
update(root[Belong[x]],1,n,y-Grade[x],tree[x]);
Grade[x]=y;
}
if(opt[1]=='S'){
cout<<Getsum(x,y,Belong[x])<<'\n';
}
if(opt[1]=='M'){
cout<<Getmax(x,y,Belong[x])<<'\n';
}
}
return 0;
}