这年头还有人帮忙调树剖吗()

P4114 Qtree1

残碑小筑 @ 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


|