残碑小筑 @ 2021-10-04 14:40:13
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define maxn(x) t[x].maxn
#define lc 2*p
#define rc 2*p+1
il int read() {
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar();}
while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int N=3e5+10;
int n,a[N];
struct edge{
int t,nex,v;
} e[N*2]; int head[N],tot,x[N],y[N];
il void add(int u,int v,int w) {
e[++tot].nex=head[u]; e[tot].t=v; e[tot].v=w; head[u]=tot;
}
//
int dep[N],num[N],son[N],fa[N];
void dfs1(int x) {
num[x]++;
int maxnum=0;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].t;
if(y==fa[x]) continue;
fa[y]=x; dep[y]=dep[x]+1; a[y]=e[i].v;
dfs1(y);
num[x]+=num[y];
if(num[y]>maxnum) {
maxnum=num[y];
son[x]=y;
}
}
}
//预处理dep,son,num,fath
int topf[N],id[N],val[N];
void dfs2(int x) {
id[x]=++tot; val[tot]=a[x];
if(!son[x]) return;
topf[son[x]]=topf[x];
dfs2(son[x]);
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].t;
if(y==fa[x] || y==son[x]) continue;
topf[y]=y;
dfs2(y);
}
}
int LCA(int x,int y) {
while(topf[x]!=topf[y]) {
if(dep[topf[x]]<dep[topf[y]]) swap(x,y);
x=fa[topf[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
struct SgTree{
int maxn;
} t[N*4]; int cnt;
void pushup(int p) {
maxn(p)=max(maxn(lc),maxn(rc));
}
void build(int p,int l,int r) {
if(l==r) {
maxn(p)=val[l];
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
void change(int p,int l,int r,int k,int x) {
if(l==r) {
maxn(p)=x;
return;
}
int mid=(l+r)/2;
if(k<=mid) change(lc,l,mid,k,x);
else change(rc,mid+1,r,k,x);
pushup(p);
}
int query(int p,int l,int r,int x,int y) {
if(l>=x && r<=y) return maxn(p);
int mid=(l+r)/2,ansn=0;
if(x<=mid) ansn=max(ansn,query(lc,l,mid,x,y));
if(y>mid) ansn=max(ansn,query(rc,mid+1,r,x,y));
return ansn;
}
int ask(int x,int y) {
int ansn=0;
while(topf[x]!=topf[y]) {
if(dep[topf[x]]<dep[topf[y]]) swap(x,y);
ansn=max(ansn,query(1,1,n,id[topf[x]],id[x]));
x=fa[topf[x]];
}
if(dep[x]<dep[y]) swap(x,y);
ansn=max(ansn,query(1,1,n,id[y],id[x]));
return ansn;
}
void print(int x) {
printf("%d ",x);
}
int main() {
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n=read();
for(int i=1;i<n;i++) {
x[i]=read(); y[i]=read();
int w=read();
add(x[i],y[i],w); add(y[i],x[i],w);
}
dep[1]=1;
dfs1(1);
tot=0; topf[1]=1;
dfs2(1);
build(1,1,n);
// string s; cin>>s;
// for(int i=1;i<=n;i++) printf("%d ",topf[i]);
string s; cin>>s;
while(s!="DONE") {
if(s=="QUERY") {
int x=read(),y=read();
printf("%d\n",ask(x,y));
}
if(s=="CHANGE") {
int k=read(),x=read();
change(1,1,n,id[y[k]],x);
}
cin>>s;
}
return 0;
}
/*
5
1 2 1
2 3 2
2 4 1
1 5 2
*/
by StevenLu1103 @ 2021-10-04 14:41:46
@celebrimbor
by _脑波_ @ 2021-10-04 14:55:35
当年我树剖调了半天
by Utilokasteinn @ 2021-10-04 15:00:13
@残碑小筑 在你的代码中101行,改为
ansn=max(ansn,query(1,1,n,id[y]+1,id[x]));
就行了
调树剖不易,能否给个关注qwq
by Utilokasteinn @ 2021-10-04 15:01:49
@残碑小筑 关于树剖更改两点之间的路径而非两点之间的点,只需要在修改或查询的最后,上面的那个点+1就可以避过那个点
by 残碑小筑 @ 2021-10-04 15:04:23
@еcho 谢谢!
by Utilokasteinn @ 2021-10-04 15:11:20
@残碑小筑 一般来说,树剖求两点之间的路径(而非点)是将路径存进它下方的节点中
这样子求的时候就不能包含它的 LCA,而在最后在同一条重边的时候将上面那个点的位置+1就可以跳过LCA
所以说能给个关注吗(因为差一个就30了
by Utilokasteinn @ 2021-10-04 15:11:49
感谢关注qwq