Re 20求调
查看原帖
Re 20求调
757101
junee楼主2024/8/30 08:47

纯线段树合并。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<random>
#include<chrono>
#include<vector>
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
typedef long long LL;
const int N=3e5+10;
int h[N],e[N*2],ne[N*2],idx;
int w[N];
int dep[N],sz[N],son[N],fa[N];
int top[N];
int n,m,mp;
int root[N][3],cnt;
int ans[N];
int stk[N],tt;
struct people{
    int s,lca,type;
};
vector<people>add[N],del[N*2];
int newnode(){
	if(tt)return stk[tt--];
	return ++cnt;
}
void Add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs_son(int u,int f,int d){
    dep[u]=d,fa[u]=f,sz[u]=1;
    mp=max(mp,dep[u]);
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==f)continue;
        dfs_son(j,u,d+1);
        sz[u]+=sz[j];
        if(sz[son[u]]<sz[j])son[u]=j;
    }
}
void dfs(int u,int t){
    top[u]=t;
    if(!son[u])return;
    dfs(son[u],t);
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==fa[u]||j==son[u])continue;
        dfs(j,j);
    }
}
int lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    return u;
}
struct node{
    int ls,rs,sum;
}tr[N*42][3];
void pushup(int u,int s){
    tr[u][s].sum=tr[tr[u][s].ls][s].sum+tr[tr[u][s].rs][s].sum;
}
int insert(int p,int l,int r,int pos,int k,int s){
    int q=newnode();
    tr[q][s]=tr[p][s];
    if(l==r){
        tr[q][s].sum+=k;
        return q;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)tr[q][s].ls=insert(tr[p][s].ls,l,mid,pos,k,s);
    else tr[q][s].rs=insert(tr[p][s].rs,mid+1,r,pos,k,s);
    pushup(q,s);
    return q;
}
int query(int u,int l,int r,int pos,int s){
    if(l==r)return tr[u][s].sum;
    int mid=(l+r)>>1;
    if(pos<=mid)return query(tr[u][s].ls,l,mid,pos,s);
    else return query(tr[u][s].rs,mid+1,r,pos,s);
}
int merge(int x,int y,int l,int r,int s){
    if(!x||!y)return x+y;
	stk[++tt]=y;
    if(l==r){
        tr[x][s].sum+=tr[y][s].sum;
        return x;
    }
    int mid=(l+r)>>1;
    tr[x][s].ls=merge(tr[x][s].ls,tr[y][s].ls,l,mid,s);
    tr[x][s].rs=merge(tr[x][s].rs,tr[y][s].rs,mid+1,r,s);
    pushup(x,s);
    return x;
}
void dfs_merge(int u,int f){
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==f)continue;
        dfs_merge(j,u);
        for(int k=0;k<3;k++)
            root[u][k]=merge(root[u][k],root[j][k],1,3*mp+1,k);
    }
    for(int i=0;i<add[u].size();i++){
        int id=add[u][i].type;
        if(id==0||id==2)
            root[u][id]=insert(root[u][id],1,3*mp+1,dep[add[u][i].s]+mp+1,1,id);
        else
            root[u][id]=insert(root[u][id],1,3*mp+1,dep[add[u][i].s]-2*dep[add[u][i].lca]+mp+1,1,id);
    }
    ans[u]+=query(root[u][0],1,3*mp+1,dep[u]-w[u]+mp+1,0);
    ans[u]+=query(root[u][1],1,3*mp+1,w[u]-dep[u]+mp+1,1);
    ans[u]+=query(root[u][2],1,3*mp+1,dep[u]+w[u]+mp+1,2);
    for(int i=0;i<del[u].size();i++){
        int id=del[u][i].type;
        if(id==0||id==2)
            root[u][id]=insert(root[u][id],1,3*mp+1,dep[del[u][i].s]+mp+1,-1,id);
        else
            root[u][id]=insert(root[u][id],1,3*mp+1,dep[del[u][i].s]-2*dep[del[u][i].lca]+mp+1,-1,id);
    }
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	memset(h,-1,sizeof h);
	cin>>n>>m;
	for(int i=1;i<n;i++){
	    int a,b;
	    cin>>a>>b;
	    Add(a,b),Add(b,a);
	}
	for(int i=1;i<=n;i++)cin>>w[i];
	dfs_son(1,-1,1);
	dfs(1,1);
	for(int i=1;i<=m;i++){
	    int s,t;
	    cin>>s>>t;
	    int Lca=lca(s,t);
	    if(Lca==s){
	        add[s].push_back({s,Lca,0});//插 s
            add[t].push_back({s,Lca,1});//插 t
            del[Lca].push_back({s,Lca,0});//删 s
            del[Lca].push_back({s,Lca,1});//删 t
	    }
	    else if(Lca==t){
	        add[s].push_back({s,Lca,2});//插 s
            add[t].push_back({s,Lca,1});//插 t
            del[Lca].push_back({s,Lca,2});//删 s
            del[Lca].push_back({s,Lca,1});//删 t
	    }
	    else{
	        add[s].push_back({s,Lca,2});//插 s
            add[t].push_back({s,Lca,1});//插 t
            del[Lca].push_back({s,Lca,2});//删 s
            del[Lca].push_back({s,Lca,1});//删 t
	    }
	    if(s==Lca&&!w[s])ans[s]--;
	    else if(t==Lca&&dep[s]-dep[t]==w[t])ans[t]--;
	    else if(Lca!=t&&Lca!=s&&dep[s]==w[Lca]+dep[Lca]&&dep[s]-2*dep[Lca]==w[Lca]-dep[Lca])ans[Lca]--;
	}
	dfs_merge(1,-1);
	for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
	return 0;
}
2024/8/30 08:47
加载中...