MnZn 求调树剖板子
查看原帖
MnZn 求调树剖板子
324666
diqiuyi奶龙楼主2023/11/14 15:35

rt,过不了样例

#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return f*x;
}
int n,q,u,v,x,opt,root=1,a[100005],cnt,top[100005],siz[100005],dep[100005],
dfn[100005],dnf[100005],f[100005],son[100005],head[100005],cnt2;
ll t[200005],lz[200005];
struct edge{
    int v,nxt;
}e[200005];
inline void Add(int u,int v){
    e[++cnt2].nxt=head[u],e[cnt2].v=v,head[u]=cnt2;
}
void dfs1(int x,int fa){
    dep[x]=dep[fa]+1,f[x]=fa,siz[x]=1;
    for(int i=head[x];i;i=e[i].nxt)
        if(e[i].v^fa)
            dfs1(e[i].v,x),siz[x]+=siz[e[i].v],son[x]=(son[x]&&siz[son[x]]>siz[e[i].v]?son[x]:e[i].v);
}
void dfs2(int x,int tp){
    dfn[x]=++cnt,dnf[cnt]=x,top[x]=tp;
    if(!son[x]) return ;
    dfs2(son[x],tp);
    for(int i=head[x];i;i=e[i].nxt)
        if(!dfn[e[i].v])
            dfs2(e[i].v,e[i].v);
}
inline int lca(int x,int y){
    while(top[x]^top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        x=f[top[x]]; 
    }
    return dep[x]<dep[y]?x:y;
}
inline int getlca(int x,int y){
    int a=lca(x,root),b=lca(y,root),c=lca(x,y);
    if(dep[a]<dep[b]) a=b;
    if(dep[a]<dep[c]) a=c;
    return a;
}
inline int ft(int x,int k){
    while(dep[x]-dep[top[x]]<k) k-=(dep[x]-dep[top[x]]+1),x=f[top[x]];
    return dnf[dfn[x]-k];
}
void build(int p,int l,int r){
    if(l==r){
        t[p]=a[dnf[l]];
        return ;
    }
    int mid=l+r>>1;
    build(mid<<1,l,mid);
    build(mid<<1|1,mid+1,r);
    t[p]=t[mid<<1]+t[mid<<1|1];
}
ll query(int p,int l,int r,int lt,int rt){
    if(lt<=l&&r<=rt) return t[p];
    int mid=l+r>>1;
    ll res=0;
    if(lz[p])
        lz[mid<<1]+=lz[p],lz[mid<<1|1]+=lz[p],t[mid<<1]+=1ll*(mid-l+1)*lz[p],t[mid<<1|1]+=1ll*(r-mid)*lz[p],lz[p]=0;
    if(lt<=mid) res+=query(mid<<1,l,mid,lt,rt);
    if(rt>mid) res+=query(mid<<1|1,mid+1,r,lt,rt);
    return res;
}
void Add(int p,int l,int r,int lt,int rt,int val){
    if(lt<=l&&r<=rt){
        lz[p]+=val,t[p]+=1ll*(r-l+1)*val;
        return ;
    }
    int mid=l+r>>1;
    ll res=0;
    if(lz[p])
        lz[mid<<1]+=lz[p],lz[mid<<1|1]+=lz[p],t[mid<<1]+=1ll*(mid-l+1)*lz[p],t[mid<<1|1]+=1ll*(r-mid)*lz[p],lz[p]=0;
    if(lt<=mid) res+=query(mid<<1,l,mid,lt,rt);
    if(rt>mid) res+=query(mid<<1|1,mid+1,r,lt,rt);
    t[p]=t[mid<<1]+t[mid<<1|1];
}
inline void upd(int x,int val){
    if(root==x)
        return Add(1,1,n,1,n,val);
    if(lca(root,x)^x)
        return Add(1,1,n,dfn[x],dfn[x]+siz[x]-1,val);
    int kf=ft(root,dep[root]-dep[x]-1);
    Add(1,1,n,1,n,val),Add(1,1,n,dfn[kf],dfn[kf]+siz[kf]-1,-val);
}
inline ll sum(int p){
    if(root==p) return t[1];
    if(lca(root,p)^p)
        return query(1,1,n,dfn[p],dfn[p]+siz[p]-1);
    int kf=ft(root,dep[root]-dep[p]-1);
    // printf("%d\n",kf);
    return t[1]-query(1,1,n,dfn[kf],dfn[kf]+siz[kf]-1);
}
int main(){
    n=read(),q=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<n;i++)
        u=read(),v=read(),Add(u,v),Add(v,u);
    dfs1(1,0);
    dfs2(1,1);    
    build(1,1,n);
    // cout<<cnt<<' '<<cnt2<<endl;
    // printf("%d\n",ft(4,1));
    while(q--){
        opt=read();
        if(opt==1) root=read();
        else if(opt==2){
            u=read(),v=read(),x=read();
            int lc=getlca(u,v);
            // printf("%d\n",lc);
            upd(lc,x);
            // cout<<"f"<<endl;
        }
        else v=read(),printf("%lld\n",sum(v));
    }
	return 0;
}
2023/11/14 15:35
加载中...