洛谷和网上的题解都是边权下传到点权,再用正常树链剖分,可是更显然的做法不是把一条边拆成两条边一个点,新点的权就是原来的边权
这样甚至都不用考虑边界问题 AC code
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10,M=N*2;
const int INF=10010;
int h[N],e[M],ne[M],idx;
int w[N],top[N],id[N],di[N],son[N],sz[N];
int cnt;
int n;
void add(int a,int b){
e[idx]=b; ne[idx]=h[a]; h[a]=idx++;
}
struct node{
int l,r;
int type,maxv,minv,sum,tag;
}tr[N*4];
void pushup(node &u,node &l,node &r){
//if(l.type)l.sum=0; if(r.type)r.sum=0;
u.sum=l.sum+r.sum;
//if(l.type)l.maxv=-INF; if(r.type) r.maxv=-INF;
u.maxv=max(l.maxv,r.maxv);
//if(l.type)l.minv=INF; if(r.type )r.minv=INF;
u.minv=min(l.minv,r.minv);
}
void pushup(int u){
pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void pushdown(int root){
node &u=tr[root],&l=tr[root<<1],&r=tr[root<<1|1];
if(u.tag){
l.tag^=1; l.sum*=-1; int t=l.maxv; l.maxv=-l.minv; l.minv=-t;
r.tag^=1; r.sum*=-1; t=r.maxv; r.maxv=-r.minv; r.minv=-t;
u.tag=0;
}
}
void build(int u,int l,int r){
if(l==r){
int xx=di[l];
if(xx>=0&&xx<=n-1)tr[u]={l,r,1,-INF,INF,0,0};
else tr[u]={l,r,0,w[xx],w[xx],w[xx],0};
}
else {
tr[u]={l,r};
int mid=l+r>>1;
build(u<<1,l,mid); build(u<<1|1,mid+1,r);
pushup(u);
}
}
void modify1(int u,int pos,int v){
if(tr[u].l==tr[u].r){
tr[u]={pos,pos,0,v,v,v,0};
return ;
}
else {
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(pos<=mid)modify1(u<<1,pos,v);
else modify1(u<<1|1,pos,v);
pushup(u);
}
}
void modify2(int u,int l,int r){
if(l<=tr[u].l&&tr[u].r<=r){
node &root=tr[u];
root.tag^=1; root.sum*=-1; int t=root.maxv; root.maxv=-root.minv; root.minv=-t;
return;
}
else {
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid)modify2(u<<1,l,r);
if(r>mid)modify2(u<<1|1,l,r);
pushup(u);
}
}
node query(int u,int l,int r){
if(l<=tr[u].l&&tr[u].r<=r){
return tr[u];
}
else {
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(r<=mid)return query(u<<1,l,r);
if(l>mid)return query(u<<1|1,l,r);
node res,left,right;
left=query(u<<1,l,r); right=query(u<<1|1,l,r);
pushup(res,left,right);
return res;
}
}
int dep[N],f[N];
void dfs1(int u,int fa,int depth){
dep[u]=depth+1; f[u]=fa; sz[u]=1; son[u]=-1;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa)continue;
dfs1(j,u,depth+1);
sz[u]+=sz[j];
if(son[u]==-1||sz[j]>sz[son[u]])son[u]=j;
}
}
void dfs2(int u,int fa,int t){
top[u]=t; id[u]=++cnt; di[cnt]=u;
if(son[u]==-1)return;
dfs2(son[u],u,t);
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa||j==son[u])continue;
dfs2(j,u,j);
}
}
int query_sum(int u,int v){
int res=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
res+=query(1,id[top[u]],id[u]).sum;
u=f[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
res+=query(1,id[v],id[u]).sum;
return res;
}
void out(int u){
if(tr[u].l==tr[u].r){
cout<<tr[u].sum<<' ';
}
else {
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
out(u<<1); out(u<<1|1);
}
}
void debug(){
out(1); cout<<endl;
}
int query_maxv(int u,int v){
int res=-1002;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
res=max(res,query(1,id[top[u]],id[u]).maxv);
u=f[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
res=max(res,query(1,id[v],id[u]).maxv);
return res;
}
int query_minv(int u,int v){
int res=1002;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
res=min(res,query(1,id[top[u]],id[u]).minv);
u=f[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
res=min(res,query(1,id[v],id[u]).minv);
return res;
}
void modify_path(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
modify2(1,id[top[u]],id[u]);
u=f[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
modify2(1,id[v],id[u]);
}
int main(){
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,n+i); add(n+i,b);
add(n+i,a); add(b,n+i);
w[n+i]=c;
}
dfs1(1,1e9,0);
dfs2(1,1e9,1);
build(1,1,cnt);
int m;scanf("%d",&m);
while(m--){
//debug();
char op[5];
scanf("%s",op);
//cout<<op<<' ';
if(!strcmp(op,"C")){
int i,v;
scanf("%d%d",&i,&v);
w[n-1+i]=v;modify1(1,id[n-1+i],v);
}
else if(!strcmp(op,"N")){
int u,v;
scanf("%d%d",&u,&v);
modify_path(u,v);
}
else if(!strcmp(op,"SUM")){
int u,v; scanf("%d%d",&u,&v);
cout<<query_sum(u,v)<<endl;
}
else if(!strcmp(op,"MAX")){
int u,v; scanf("%d%d",&u,&v);
cout<<query_maxv(u,v)<<endl;
}
else {
int u,v; scanf("%d%d",&u,&v);
cout<<query_minv(u,v)<<endl;
}
}
}