Description
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
操作有如下五种形式: C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。 N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。 SUM u v,表示询问从景点u 到v 所获得的总愉悦度。 MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。 MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。
Hint
一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。
Solution
裸的树链剖分,这里边的边权可以看成是较低节点的点权,然后取反操作就是最大最小值互换取反,sum取反就行了
细节挺多,码农题
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
const int INF=0x7fffffff;
const int N=400005;
const int E=800005;
struct edge{int x,y,w,next;}e[E];
int ls[N],edCnt=0;
int lazy[N],sum[N],mx[N],mn[N];
int size[N],son[N],len[N],pos[N],dep[N],fa[N],bl[N],cnt=0;
int n,m;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void addEdge(int x,int y,int w) {
e[++edCnt]=(edge){x,y,w,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge){y,x,w,ls[y]}; ls[y]=edCnt;
}
void swap(int &x,int &y) {x^=y; y^=x; x^=y;}
void oppo(int x) {
swap(mx[x],mn[x]);
mx[x]*=-1; mn[x]*=-1;
sum[x]*=-1;
}
void dfs1(int now) {
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa[now]) {continue;}
fa[e[i].y]=now;
dep[e[i].y]=dep[now]+1;
len[e[i].y]=e[i].w;
dfs1(e[i].y);
size[now]+=size[e[i].y];
}
}
void dfs2(int now,int up) {
pos[now]=++cnt; bl[now]=up;
int mx=0;
for (int i=ls[now];i;i=e[i].next) {
if (dep[e[i].y]>dep[now]&&size[e[i].y]>size[mx]) {mx=e[i].y;}
}
if (!mx) {return ;}
son[now]=mx;
dfs2(mx,up);
for (int i=ls[now];i;i=e[i].next) {
if (dep[e[i].y]>dep[now]&&e[i].y!=mx) {dfs2(e[i].y,e[i].y);}
}
}
void push_down(int now) {
if (!lazy[now]) {return ;}
lazy[now<<1]^=lazy[now];
// if (lazy[now<<1]) {oppo(now<<1);}
oppo(now<<1);
lazy[now<<1|1]^=lazy[now];
// if (lazy[now<<1|1]) {oppo(now<<1|1);}
oppo(now<<1|1);
lazy[now]=0;
}
void push_up(int now) {
mx[now]=max(mx[now<<1],mx[now<<1|1]);
mn[now]=min(mn[now<<1],mn[now<<1|1]);
sum[now]=sum[now<<1]+sum[now<<1|1];
}
int query(int now,int tl,int tr,int l,int r,int opt) {
push_down(now);
if (tl==l&&tr==r) {
if (opt==0) {return mx[now];}
else if (opt==1) {return mn[now];}
else if (opt==2) {return sum[now];}
}
int mid=(tl+tr)>>1;
if (r<=mid) {return query(now<<1,tl,mid,l,r,opt);}
else if (l>mid) {return query(now<<1|1,mid+1,tr,l,r,opt);}
else {
int retx=query(now<<1,tl,mid,l,mid,opt);
int rety=query(now<<1|1,mid+1,tr,mid+1,r,opt);
if (opt==0) {return max(retx,rety);}
else if (opt==1) {return min(retx,rety);}
else if (opt==2) {return retx+rety;}
}
}
void modify(int now,int tl,int tr,int l,int r,int v,int opt) {
push_down(now);
if (tl==l&&tr==r) {
if (opt==1) {oppo(now); lazy[now]=1;}
else {mx[now]=mn[now]=sum[now]=v;}
return ;
}
int mid=(tl+tr)>>1;
if (r<=mid) {modify(now<<1,tl,mid,l,r,v,opt);}
else if (l>mid) {modify(now<<1|1,mid+1,tr,l,r,v,opt);}
else {
modify(now<<1,tl,mid,l,mid,v,opt);
modify(now<<1|1,mid+1,tr,mid+1,r,v,opt);
}
push_up(now);
}
int get_ans(int x,int y,int opt) {
int ret;
if (opt==0) {ret=-INF;}
else if (opt==1) {ret=INF;}
else if (opt==2) {ret=0;}
while (bl[x]!=bl[y]) {
if (dep[bl[x]]<dep[bl[y]]) {swap(x,y);}
if (opt==0) {ret=max(ret,query(1,1,n,pos[bl[x]],pos[x],0));}
else if (opt==1) {ret=min(ret,query(1,1,n,pos[bl[x]],pos[x],1));}
else if (opt==2) {ret+=query(1,1,n,pos[bl[x]],pos[x],2);}
x=fa[bl[x]];
}
if (x==y) {return ret;}
if (dep[x]>dep[y]) {swap(x,y);}
x=son[x];
if (opt==0) {ret=max(ret,query(1,1,n,pos[x],pos[y],0));}
else if (opt==1) {ret=min(ret,query(1,1,n,pos[x],pos[y],1));}
else if (opt==2) {ret+=query(1,1,n,pos[x],pos[y],2);}
return ret;
}
void solve_oppo(int x,int y) {
while (bl[x]!=bl[y]) {
if (dep[bl[x]]<dep[bl[y]]) {swap(x,y);}
modify(1,1,n,pos[bl[x]],pos[x],0,1);
x=fa[bl[x]];
}
if (x==y) {return ;}
if (dep[x]>dep[y]) {swap(x,y);}
x=son[x];
modify(1,1,n,pos[x],pos[y],0,1);
}
void buildTree(int now,int l,int r) {
mx[now]=-INF;
mn[now]=INF;
sum[now]=0;
if (l==r) {return ;}
int mid=(l+r)>>1;
buildTree(now<<1,l,mid);
buildTree(now<<1|1,mid+1,r);
push_up(now);
}
void solve() {
dfs1(1);
dfs2(1,1);
buildTree(1,1,n);
rep(i,1,n) {modify(1,1,n,pos[i],pos[i],len[i],2);}
m=read();
rep(i,1,m) {
char opt[5]; scanf("%s",opt);
int x=read()+1,y=read()+1;
if (opt[0]=='C') {
x--,y--;
if (dep[e[x*2-1].y]>dep[e[x*2].y]) {modify(1,1,n,pos[e[x*2-1].y],pos[e[x*2-1].y],y,0);}
else {modify(1,1,n,pos[e[x*2].y],pos[e[x*2].y],y,0);}
} else if (opt[0]=='N') {
solve_oppo(x,y);
} else if (opt[0]=='S') {
int prt=get_ans(x,y,2);
printf("%d\n",prt);
} else if (opt[0]=='M'&&opt[1]=='I') {
int prt=get_ans(x,y,1);
printf("%d\n",prt);
} else if (opt[0]=='M'&&opt[1]=='A') {
int prt=get_ans(x,y,0);
printf("%d\n",prt);
}
}
}
void init() {
n=read();
rep(i,2,n) {
int x=read()+1;
int y=read()+1;
int w=read();
addEdge(x,y,w);
}
}
int main(void) {
init();
solve();
return 0;
}