关于做法
查看原帖
关于做法
836104
cxlian25楼主2023/1/11 16:11

本人把树剖板子题的细节修改了下,并没有考虑差分的做法,吸口氧才过,这题如果用树剖的话可以进行这样的优化吗

#include <bits/stdc++.h>
#define lx (x<<1)
#define rx (x<<1|1)
#define mid (l+r>>1)
using namespace std;
const int N=3e5+3;
int n,cnt=0,b[N];
int a[N]={0},fa[N],dep[N],siz[N],hson[N],dfn[N],rnk[N],top[N];
int st[N<<2],lazy[N<<2];
vector<int>edge[N];

void dfs(int x,int f,int d){
    fa[x]=f;siz[x]=1;dep[x]=d;hson[x]=0;
    for(int to: edge[x]){
        if(to==f)continue;
        dfs(to,x,d+1);
        siz[x]+=siz[to];
        if(!hson[x]||siz[hson[x]]<siz[to])
            hson[x]=to;
    }
}
void dfs2(int x,int f,int t){
    top[x]=t;dfn[x]=++cnt;rnk[cnt]=x;
    if(!hson[x])return;
    dfs2(hson[x],x,t);
    for(int to: edge[x]){
        if(to==hson[x]||to==f)continue;
        dfs2(to,x,to);
    }
}
//以上为树链剖分的两次dfs 
void build(int x,int l,int r){
    if(l==r){
        st[x]=0;
        return;
    }
    build(lx,l,mid);
    build(rx,mid+1,r);
    st[x]=st[lx]+st[rx];
}
void up(int x,int l,int r,int w){
    st[x]+=(r-l+1)*w;
    lazy[x]+=w;
}
void down(int x,int l,int r){
    up(lx,l,mid,lazy[x]);
    up(rx,mid+1,r,lazy[x]);
    lazy[x]=0;
}
void update(int x,int l,int r,int sl,int sr,int w){
    if(sl>r||sr<l)return;
    if(sr>=r&&sl<=l){
        up(x,l,r,w);
        return;
    }
    down(x,l,r);
    update(lx,l,mid,sl,sr,w);
    update(rx,mid+1,r,sl,sr,w);
    st[x]=st[lx]+st[rx];
}
int query(int x,int l,int r,int sl,int sr){
    if(sl>r||sr<l)return 0;
    if(sr>=r&&sl<=l)return st[x];
    down(x,l,r);
    return query(lx,l,mid,sl,sr)+query(rx,mid+1,r,sl,sr);
}
void luadd(int x,int y,int w){
    while(top[x]!=top[y]){
        if(dep[top[x]]>=dep[top[y]]){
            update(1,1,n,dfn[top[x]],dfn[x],w);
            x=fa[top[x]];
        }
        else{
            update(1,1,n,dfn[top[y]],dfn[y],w);
            y=fa[top[y]];
        }
    }
    if(dep[x]>dep[y])update(1,1,n,dfn[y],dfn[x],w);
    else update(1,1,n,dfn[x],dfn[y],w);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    dfs(b[1],0,1);
    dfs2(b[1],0,b[1]);
    build(1,1,n);
    for(int i=1;i<n;i++){
        luadd(b[i],b[i+1],1);
        luadd(b[i+1],b[i+1],-1);
    }
    for(int i=1;i<=n;i++){
        printf("%d\n",query(1,1,n,dfn[i],dfn[i]));
    }
    return 0;
}

本来想着不用建树,没想到不建树过不了编译,真是奇怪

2023/1/11 16:11
加载中...