[bzoj3307] tail in rainy days [line tree]

Keywords: PHP

[title link]
  http://www.lydsy.com/JudgeOnline/problem.php?id=3307
[Abstract]
First of all, all the changes of this problem can be handled at one time.
If there is an edge (u,v)(u,v), put a + 1 + 1 mark on u,vu,v respectively, put a − 1 − 1 mark on LCA (U, V), Dad (U, V)) LCA (U, V), Dad (U, V)).
Now consider how to count the answer, dfs traverses the whole tree, each node records the mark with the weight line tree, and uploads the mark every time when backtracking, and each node counts after all its sons are counted.
The complexity of statistics is obviously O(nlogz)O(nlogz). Now the problem is how to merge two weight line segment trees. Considering the merging method of left leaning tree, we can imitate it as follows:
It is basically the same as the left leaning tree, but slightly modified at the leaf node.

int merge(int x, int y, int l, int r){
    if (x==0) return y;
    if (y==0) return x;
    if (l==r){
        T[x].num+=T[y].num;
        return x;
    }
    int mid=(l+r)/2;
    T[x].pl=merge(T[x].pl,T[y].pl,l,mid); T[x].pr=merge(T[x].pr,T[y].pr,mid+1,r);
    return x;
}

If there are nn leaf nodes with values in mm, then the time complexity is O(nlogm)O(nlogm). Next, a section of Kouhu is given:
If a node contains an interval with k k values, at least 22 values will be merged each time it accesses this interval, so the interval will be accessed O(k)O(k) times at most, and a value will be included in logmlogm intervals, so the total complexity is O(nlogm)O(nlogm)

/* --------------
    user Vanisher
    problem bzoj-3307 
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    N       100010
# define    L       17
# define    LL      1
# define    RR      1e9
using namespace std;
int read(){
    int tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
struct Tree{
    int num,id,pl,pr;
}T[4000100];
struct node{
    int data,next;
}e[N*2];
vector <int> add[N],del[N];
int place,head[N],dad[N][L+1],dep[N],n,rt[N],ans[N],m;
void build(int u, int v){
    e[++place].data=u; e[place].next=head[v]; head[v]=place;
    e[++place].data=v; e[place].next=head[u]; head[u]=place;
}
void dfs(int x, int fa){
    dad[x][0]=fa; dep[x]=dep[fa]+1;
    for (int ed=head[x]; ed!=0; ed=e[ed].next)
        if (e[ed].data!=fa)
            dfs(e[ed].data,x);
}
void pre(){
    for (int i=1,j=1; j*2<=n; i++, j*=2)
        for (int k=1; k<=n; k++)
            dad[k][i]=dad[dad[k][i-1]][i-1];
}
int lca(int x, int y){
    if (dep[x]>dep[y]) swap(x,y);
    for (int i=L; i>=0; i--)
        if (dep[dad[y][i]]>=dep[x])
            y=dad[y][i];
    if (x==y) return x;
    for (int i=L; i>=0; i--)
        if (dad[x][i]!=dad[y][i])
            x=dad[x][i], y=dad[y][i];
    return dad[x][0];
}
void change(int p){
    if (T[T[p].pl].num>=T[T[p].pr].num)
        T[p].num=T[T[p].pl].num, T[p].id=T[T[p].pl].id;
        else T[p].num=T[T[p].pr].num, T[p].id=T[T[p].pr].id;
}
int extend(int x, int y, int l, int r){
    if (x==0) return y;
    if (y==0) return x;
    if (l==r){
        T[x].num+=T[y].num;
        T[x].id=l; 
        return x;
    }
    int mid=(l+r)/2;
    T[x].pl=extend(T[x].pl,T[y].pl,l,mid); T[x].pr=extend(T[x].pr,T[y].pr,mid+1,r);
    change(x);
    return x;
}
int inc(int p, int x, int l, int r){
    if (p==0) p=++place;
    if (l==r) {
        T[p].num++;
        T[p].id=x;
        return p;
    }
    int mid=(l+r)/2;
    if (x<=mid) T[p].pl=inc(T[p].pl,x,l,mid);
        else T[p].pr=inc(T[p].pr,x,mid+1,r);
    change(p);
    return p;
}
int dec(int p, int x, int l, int r){
    if (p==0) p=++place;
    if (l==r) {
        T[p].num--;
        if (T[p].num==0) T[p].id=0;
        return p;
    }
    int mid=(l+r)/2;
    if (x<=mid) T[p].pl=dec(T[p].pl,x,l,mid);
        else T[p].pr=dec(T[p].pr,x,mid+1,r);
    change(p);
    return p;
}
int getans(int x){
    return T[x].id;
}
void solve(int x, int fa){
    int now=0;
    for (int ed=head[x]; ed!=0; ed=e[ed].next)
        if (e[ed].data!=fa){
            solve(e[ed].data,x);
            now=e[ed].data;
        }
    rt[x]=rt[now];
    for (int ed=head[x]; ed!=0; ed=e[ed].next)
        if (e[ed].data!=fa&&e[ed].data!=now)
            rt[x]=extend(rt[x],rt[e[ed].data],LL,RR);
    for (int i=0; i<add[x].size(); i++)
        rt[x]=inc(rt[x],add[x][i],LL,RR);
    for (int i=0; i<del[x].size(); i++)
        rt[x]=dec(rt[x],del[x][i],LL,RR);
    ans[x]=getans(rt[x]);
}
int main(){
    n=read(), m=read();
    for (int i=1; i<n; i++)
        build(read(),read());
    place=0;
    dfs(1,0); pre();
    for (int i=1; i<=m; i++){
        int u=read(), v=read(), k=read();
        int l=lca(u,v);
        del[l].push_back(k);
        add[u].push_back(k);
        add[v].push_back(k);
        del[dad[l][0]].push_back(k);
    }
    solve(1,0);
    for (int i=1; i<=n; i++)
        printf("%d\n",ans[i]);
    return 0;
}

Posted by Dr John on Wed, 01 Apr 2020 23:53:09 -0700