Running every day segment tree merger

Running every day segment tree merger

The combined approach using segment tree

There path \ (u_i-> LCA (u_i, V_I) -> V_I \) , the path is divided into two halves discussed separately.

Consider \ (u_i-> lca (u_i, v_i) \) before the half way:

Node \ (X \) contribute, if and only if \ (DEP [u_i] -dep [X] = W [X] \) , transposition-containing \ (X \) is on one side to make it easier statistics \ (DEP [u_i] = W [X] + DEP [X] \) , so that only the node statistical \ (X \) within the path of the subtree starting depth \ (w [x] + dep [x] \) th number.

\ (lca-> v_i \) after half way empathy:

Node \ (X \) contribute, if and only if \ (DEP [V_I] -dep [X] = DIS-W [X] \) , where \ (DIS \) of \ (u, v \) path length, the same for statistical purposes,The use of parametric on separationWe have to move items \ (DEP [v_i], DIS = DEP [the X-] -w [the X-] \) , then you can put \ (dis \) apart to give \ (- dep [u_i] + 2 * dep [lca] = dep [x] -w [x] \) so that only the node statistical \ (X \) those paths within the subtree end \ (V_I \) satisfies \ (dep [u_i] -2 * dep [lca] \) of \ (w [x] -dep [ x] \) is the number to.

Then consider how statistics. Violence enumeration sub-tree with statistics subtree answer is definitely fried, can be combined with a bucket or tree line or DSU on Tree Statistics.

As used herein segment tree merge, becauseAddictedCan be directly put on the board does not need a tree difference discussions difficulty thinking so small.

Two paths open a set of weights for each segment tree, the subscript \ (DEP \) , and then apply differential thinking. In \ (u-> lca \) segment tree on a path, in \ (U \) at +1, then the \ (LCA \) cm⁻¹; in \ (lca-> v \) path, in \ (V \) at + 1'd, \ (FA [LCA] \) at -1, thus ensuring the two paths merge information.

Then node \ (x \) of the tree line and the answer is two sets of query results and.

#include <cstdio>
#include <algorithm>
#define MAXN 300003
using namespace std;
inline int read(){
    char ch=getchar();int s=0;bool w=0;
    while((ch<'0'||ch>'9')&&(ch!='-')) ch=getchar();
    if(ch=='-'){w=1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+(ch^'0'),ch=getchar();
    if(w) return -s;
    return s;
}
int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot;
inline void add_egde(int u, int v){
    vv[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
int dep[MAXN],mxs[MAXN],sz[MAXN],f[MAXN];
void dfs(int u, int fa){
    sz[u]=1;
    dep[u]=dep[fa]+1;
    f[u]=fa;
    int mxsz=-1;
    for(int i=head[u];i;i=nxt[i]){
        int v=vv[i];
        if(v==fa) continue;
        dfs(v, u);
        sz[u]+=sz[v];
        if(sz[v]>mxsz){
            mxsz=sz[v];
            mxs[u]=v;
        }
    }
}
int topf[MAXN];
void dfs2(int u, int top){
    topf[u]=top;
    if(mxs[u]==0) return;
    dfs2(mxs[u], top);
    for(int i=head[u];i;i=nxt[i]){
        int v=vv[i];
        if(v==f[u]||v==mxs[u]) continue;
        dfs2(v, v);
    }
}
int lca(int a,int b){
    while(topf[a]!=topf[b]){
        if(dep[topf[a]]<dep[topf[b]]) swap(a,b);
        a=f[topf[a]];
    }
    if(dep[a]<dep[b]) return a;
    else return b;
}
int cnt;
#define MAXM MAXN*2*18*2
int tre[MAXM],sl[MAXM],sr[MAXM];
void change(int &x, int l, int r, int pos, int val){
    if(x==0) x=++cnt;
    if(l==r){
        tre[x]+=val;
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) change(sl[x], l, mid, pos, val);
    else change(sr[x], mid+1, r, pos, val);
}
int query(int x, int l, int r, int pos){
    if(x==0) return 0;
    if(l==r) return tre[x];
    int mid=(l+r)>>1;
    if(pos<=mid) return query(sl[x], l, mid, pos);
    else return query(sr[x], mid+1, r, pos);
}
int merge(int a, int b, int l, int r){
    if(a==0||b==0) return a+b;
    if(l==r){
        tre[a]+=tre[b];
        return a;
    }
    int mid=(l+r)>>1;
    sl[a]=merge(sl[a], sl[b], l, mid);
    sr[a]=merge(sr[a], sr[b], mid+1, r);
    return a;
}
int n,m,w[MAXN],rot1[MAXN],rot2[MAXN];
int ans[MAXN];
void solve(int u, int fa){
    for(int i=head[u];i;i=nxt[i]){
        int v=vv[i];
        if(v==fa) continue;
        solve(v, u);
        rot1[u]=merge(rot1[u], rot1[v], 1, n*2);
        rot2[u]=merge(rot2[u], rot2[v], 1, n*2);
    }
    ans[u]=query(rot1[u], 1, n*2, dep[u]+w[u])+query(rot2[u], 1, n*2, n+w[u]-dep[u]);
}
int main(){
    n=read(),m=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        add_egde(u, v);
    }
    dfs(1, 0);
    dfs2(1, 1);
    for(int i=1;i<=n;++i) w[i]=read();
    for(int i=1;i<=m;++i){
        int s=read(),t=read();
        int tmp=lca(s, t);
        change(rot1[s], 1, n*2, dep[s], 1);
        change(rot1[tmp], 1, n*2, dep[s], -1);
        change(rot2[t], 1, n*2, n+dep[s]-dep[tmp]*2, 1);
        change(rot2[f[tmp]], 1, n*2, n+dep[s]-dep[tmp]*2, -1);
    }
    solve(1, 1);
    for(int i=1;i<=n;++i) printf("%d ", ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/santiego/p/11770332.html