首先不难发现此题是一个树上修改。树剖是一定的。
但是,询问的是一条路上同一颜色的权值和,颜色最多有1e5种,如果每一种颜色都维护一棵线段树显然要爆空间。
此时我们可以想到离线。
先处理一种颜色的修改和询问,统计好答案清空后再处理下一种颜色。
(思路类似 SDOI2008郁闷的小J)
注意一点,这里是单点修改。如果是区间修改最坏会被卡成 n 2 n^2 n2。。。
代码细节:
一,结构体定义
c: 颜色
t:此操作的时间
f::操作类型(0:询问路径最大值 1:询问路径和 2:单点修改)
x,y:起点和终点(单点修改时标号为x)
k:单点修改的值
排序顺序:第一关键字:颜色,第二关键字:时间
struct atom{
int c,t,f,x,y,k;
bool operator <(const atom & k ) const{
return (c==k.c) ? t<k.t : c<k.c;
}
}t[1000005];
二, 改颜色处理
1.对于原来的颜色,会对之后的询问产生影响
2.对于改变后的颜色,会对之后的询问产生影响
if(s[0]=='C'){
if(s[1]=='C'){
++tim;t[tim]=(atom){col[x],tim,2,x,0,0};
col[x]=y;
++tim;t[tim]=(atom){col[x],tim,2,x,0,num[x]};
}
三,清空小技巧
可以在同种颜色的最后清空,总复杂度 O(n*logn)
for(int i=1;i<=n;++i){
++tim;t[tim]=(atom){col[i],1e9,2,i,0,0};
}
#include
using namespace std;
#define sf scanf
#define pf printf
#define lc (p<<1)
#define rc ((p<<1)|1)
#define ll long long
const int maxn=1e5+10;
int seg[maxn],top[maxn],son[maxn],dep[maxn],fa[maxn],col[maxn],mx[maxn<<2],n,m,tim=0,num[maxn],siz[maxn];
ll sum[maxn<<2];
vector <int> G[maxn];
struct atom{
int c,t,f,x,y,k;
bool operator <(const atom & k ) const{
return (c==k.c) ? t<k.t : c<k.c;
}
}t[1000005];
//f:0 getmax f: 1 getsum f:2 change
struct node{
ll t,s;
bool operator <(const node & k ) const{
return t<k.t;
}
};
vector <node> P;
inline void change(int p,int l,int r,int k,int v){
if(l==r){
sum[p]=mx[p]=v;
return;
}
int mid=(l+r)>>1;
if(k>mid) change(rc,mid+1,r,k,v);
else change(lc,l,mid,k,v);
sum[p]=sum[lc]+sum[rc];mx[p]=max(mx[lc],mx[rc]);
}
inline ll query(int p,int l,int r,int ql,int qr,bool f){
if(ql>qr)return 0;
if(ql<=l&&r<=qr){
return f ? sum[p] : mx[p];
}
int mid=(l+r)>>1;
if(ql>mid) return query(rc,mid+1,r,ql,qr,f);
else if(qr<=mid) return query(lc,l,mid,ql,qr,f);
else return f ? query(lc,l,mid,ql,qr,f)+query(rc,mid+1,r,ql,qr,f) : max(query(lc,l,mid,ql,qr,f),query(rc,mid+1,r,ql,qr,f));
}
void dfs(int u){
siz[u]=1;
for(int i=0;i<G[u].size();++i){
int v=G[u][i];if(v==fa[u])continue;
fa[v]=u;dep[v]=dep[u]+1;
dfs(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u){
int v=son[u];
if(v){
top[v]=top[u];seg[v]=++seg[0];
dfs2(v);
}
for(int i=0;i<G[u].size();++i){
v=G[u][i];if(top[v])continue;
top[v]=v;seg[v]=++seg[0];
dfs2(v);
}
}
inline ll answer(int x,int y,int f){
int fx=top[x],fy=top[y];
ll ret=0;
while(fx!=fy){
if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
ret= f? ret+query(1,1,seg[0],seg[fx],seg[x],f) : max(ret,query(1,1,seg[0],seg[fx],seg[x],f));
x=fa[fx];fx=top[x];
}
if(dep[x]>dep[y])swap(x,y);
return f? ret+query(1,1,seg[0],seg[x],seg[y],f) : max(ret,query(1,1,seg[0],seg[x],seg[y],f));
}
char s[20];
signed main(){
sf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
sf("%d%d",&num[i],&col[i]);
++tim;t[tim]=(atom){col[i],tim,2,i,0,num[i]};
}
for(int i=1;i<n;++i){
int x,y;sf("%d%d",&x,&y);
G[x].push_back(y);G[y].push_back(x);
}
top[1]=dep[1]=seg[1]=seg[0]=1;
dfs(1);dfs2(1);
for(int i=1;i<=m;++i){
sf("\n%s",s);int x,y;sf("%d%d",&x,&y);
if(s[0]=='C'){
if(s[1]=='C'){
++tim;t[tim]=(atom){col[x],tim,2,x,0,0};
col[x]=y;
++tim;t[tim]=(atom){col[x],tim,2,x,0,num[x]};
}
if(s[1]=='W'){
num[x]=y;
++tim;t[tim]=(atom){col[x],tim,2,x,0,num[x]};
}
}
if(s[0]=='Q'){
if(s[1]= ='S'){
++tim;t[tim]=(atom){col[y],tim,1,x,y,0};
}
if(s[1]=='M'){
++tim;t[tim]=(atom){col[y],tim,0,x,y,0};
}
}
}
for(int i=1;i<=n;++i){
++tim;t[tim]=(atom){col[i],1e9,2,i,0,0};
}
sort(t+1,t+tim+1);
for(int i=1;i<=tim;++i){
if(t[i].f==2){
change(1,1,seg[0],seg[t[i].x],t[i].k);
}
else P.push_back((node){t[i].t,answer(t[i].x,t[i].y,t[i].f)});
}
sort(P.begin(),P.end());
for(int i=0;i<P.size();++i){
cout<<P[i].s<<"\n";
}
return 0;
}