Luo Gu P3920 [WC2014] Bauhinia Love

Portal

I want to question five minutes, adjusting questions 20 hours $ QAQ $

I made this question of course:

What a mess this


If you have heard "scapegoat style reconstruction dotted tree", then this topic is very good think of.

Consider first the simple dotted rule:

Every partition contribution Statistics path through the center point of the partition.

Note $ dis_i $ $ I $ point distance of the center partition, i.e., the condition $ dis_i + dis_j \ le r_i + r_j $.

移 个 项: $ dis_i-r_i \ the r_j-dis_j $.

The $ r_i-dis_i $ inserted into the balanced tree, the number of queries than or equal to $ dis_i-r_i $ balanced tree.

Dynamic approach is quite clear, dotted the tree each point to open a balanced tree. But also the inclusion-exclusion subtract the contribution of the same sub-tree, with a record $ vector $ balanced tree for inclusion and exclusion of each layer.

Plus point directly at the dotted tree will $ i $ and $ a_i $ edge even violent jump dotted tree in a balanced tree Richards, and insert their own information.

Notes that hang every time a point below a certain point, while the dotted tree tree Gaoyao maintained at $ \ log $ level.

Like a balanced tree. Rotation is not possible, using the idea of ​​reconstruction points scapegoat tree points trees.

Hutchison $ siz $ dotted tree sub-tree size. When $ \ max \ limits_ {i \ in son (x)} siz_i \ ge siz_x \ times \ alpha $ ($ \ alpha $ is a balance factor, I set $ 0.7 $) of reconstructed point $ I $ subtree.

$ Asuldb $: reconfigurable multi-simple, not on the dotted rule about it.

We want to reconstruct doing ($ x $ to be reconstructed points):

  • Maintenance dotted tree each point's son, $ bfs $ reconstruct what point you want to get
  • Clear each point of balanced tree
  • Reserved non-reconstructed points of the inclusion-exclusion balanced tree, the other empty. Point noted the depth of inclusion and exclusion of $ vector $ balanced tree recorded in the dotted tree belongs is increasing. Has been pop_backand empty the balance until the end of the element tree is $ fa (x) $ can be.
  • Dotted rule reconstruction dotted tree

In order to ensure a single reconstruction complexity is $ O (siz_x \ log siz_x) $ , the information presented to the sub-tree row a direct order build. $ treap $ random weights is not good build, $ splay $ slow so chose to scapegoat tree.

(In fact false, and there is a sort reconstruction is $ O (siz_x \ log ^ 2 siz_x) $ of ...)

Also with a plus point to point distance queries can be doubled, I use $ LCT $.

Complexity is $ O (n \ log ^ 2 n) $.

Note that garbage collection.

Full details of the code is:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
#include <set>

#define maxn 100005
#define inf 0x3f3f3f3f

const double alpha = 0.7;
const int mod = 1e9;

using namespace std;

inline int read(){
    int x=0,y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
struct edge{
    int pre,to,l;
}e[maxn<<1];
struct ScapeGoatTree{
#define ls(x) son[x][0]
#define rs(x) son[x][1]
#define son(x,y) son[x][y]
    int son[maxn*50][2],dat[maxn*50],siz[maxn*50],pool[maxn*50],a[maxn<<1],len,cnt;
    bool isbad(int node){
        return 1.0*max(siz[ls(node)],siz[rs(node)])>=alpha*siz[node];
    }
    void build(int *base,int l,int r,int &node){
        if(l>r){node=0;return;}
        node=pool[cnt--];
        int mid=l+r>>1;
        dat[node]=base[mid];
        build(base,l,mid-1,ls(node));
        build(base,mid+1,r,rs(node));
        siz[node]=siz[ls(node)]+siz[rs(node)]+1;
    }
    void dfs(int node){
        if(!node)return;
        dfs(ls(node));
        a[++len]=dat[node];
        dfs(rs(node));
        pool[++cnt]=node;
    }
    int push(int &node,int d){
        if(!node){
            dat[node=pool[cnt--]]=d,siz[node]=1;
            ls(node)=rs(node)=0;
            return 0;
        }
        ++siz[node];
        int p=push(son(node,dat[node]<d),d);
        if(isbad(node))return node;
        return p;
    }
    void clear(int &node){
        if(!node)return;
        clear(ls(node)),clear(rs(node));
        pool[++cnt]=node,node=0;
    }
    void insert(int &node,int d){
        int p=push(node,d);
        if(p)len=0,dfs(p),build(a,1,len,p);
    }
    int find(int node,int x){
        int ans=0;
        while(node){
            if(dat[node]>=x)ans+=siz[rs(node)]+1,node=ls(node);
            else node=rs(node);
        }
        return ans;
    }
    ScapeGoatTree(){
        cnt=maxn*50-1;
        for(register int i=1;i<=cnt;++i)pool[i]=i;
    }
}sgt;
struct LinkCutTree{
#define whson(x) (son(fa[x],1)==x)
#define isroot(x) (son(fa[x],0)!=x&&son(fa[x],1)!=x)
    int son[maxn<<1][2],fa[maxn<<1],sum[maxn<<1],v[maxn<<1],rev[maxn<<1],sta[maxn<<1];
    inline void update(int node){
        sum[node]=sum[ls(node)]+sum[rs(node)]+v[node];
    }
    inline void addedge(int s,int f,int wh){
        if(s)fa[s]=f;
        son(f,wh)=s;
    }
    inline void reverdown(int node){
        swap(ls(node),rs(node)),rev[node]^=1;
    }
    inline void pushdown(int node){
        if(rev[node])reverdown(ls(node)),reverdown(rs(node)),rev[node]=0;
    }
    void zhuan(int x){
        int f=fa[x],gf=fa[f],wh=whson(x);
        fa[x]=gf;
        if(!isroot(f))son(gf,whson(f))=x;
        addedge(son(x,wh^1),f,wh);
        addedge(f,x,wh^1);
        update(f),update(x);
    }
    void splay(int x){
        int y=x,top=1;
        sta[1]=x;
        while(!isroot(y))sta[++top]=y=fa[y];
        while(top)pushdown(sta[top--]);
        while(!isroot(x)){
            y=fa[x];
            if(!isroot(y))zhuan(whson(y)^whson(x)?x:y);
            zhuan(x);
        }
    }
    void access(int x){
        for(register int y=0;x;y=x,x=fa[x])
            splay(x),son(x,1)=y,update(x);
    }
    void makeroot(int x){
        access(x),splay(x),reverdown(x);
    }
    void link(int x,int y){fa[x]=y;}
    int Get(int x,int y){
        makeroot(x),access(y),splay(y);
        return sum[y];
    }
}lct;
int r1[maxn],r2[maxn],h[maxn],siz[maxn],ts[maxn],pool[maxn<<2],num,cnt=(maxn<<2)-1,all,mx,root,l1,l2;
int mp[maxn],rt[maxn],exc[maxn<<3],line[maxn],dep[maxn],fa[maxn],a[maxn];
bool vis[maxn],rub[maxn<<1];
vector<int>b[maxn];
set<int>son[maxn];
inline void add(int from,int to,int l){
    e[++num].pre=h[from],h[from]=num,e[num].to=to,e[num].l=l;
}
void getroot(int node,int f=0){
    int ma=0,x;
    siz[node]=1;
    for(register int i=h[node];i;i=e[i].pre){
        x=e[i].to;
        if(x==f||vis[x])continue;
        getroot(x,node),ma=max(ma,siz[x]),siz[node]+=siz[x];
    }
    ma=max(ma,all-siz[node]);
    if(ma<mx)mx=ma,root=node;
}
void bfs(int node){
    int head=0,tail=1,rc=cnt;
    dep[line[1]=node]=0;
    while(head<tail){
        int x=line[++head];
        vis[x]=0;
        for(set<int>::iterator iter=son[x].begin();iter!=son[x].end();++iter)
            dep[line[++tail]=*iter]=dep[x]+1;
        while(dep[x]--){
            sgt.clear(exc[*b[x].rbegin()]);
            if(!rub[*b[x].rbegin()])rub[pool[++cnt]=*b[x].rbegin()]=1;
            b[x].pop_back();
        }
        sgt.clear(rt[x]);
        son[x].clear();
    }
    for(register int i=rc+1;i<=cnt;++i)rub[pool[i]]=0;
}
void dfs(int node,int len,int f){
    r1[++l1]=r2[++l2]=a[node]-len,b[node].push_back(pool[cnt]);
    siz[node]=1;
    int x;
    for(register int i=h[node];i;i=e[i].pre){
        x=e[i].to;
        if(x==f||vis[x])continue;
        dfs(x,len+e[i].l,node),siz[node]+=siz[x];
    }
}
void build(int node){
    vis[node]=ts[node]=1,mp[node]=0,r1[l1=1]=a[node];
    int x;
    for(register int i=h[node];i;i=e[i].pre){
        x=e[i].to;
        if(vis[x])continue;
        l2=0,dfs(x,e[i].l,node);
        sort(r2+1,r2+1+l2);
        sgt.build(r2,1,l2,exc[pool[cnt--]]);
    }
    sort(r1+1,r1+1+l1);
    sgt.build(r1,1,l1,rt[node]);
    for(register int i=h[node];i;i=e[i].pre){
        x=e[i].to;
        if(vis[x])continue;
        mx=inf,mp[node]=max(all=siz[x],mp[node]),getroot(x);
        ts[node]+=all,fa[root]=node,son[node].insert(root);
        build(root);
    }
}
void rebuild(int node){
    int x=node,p=0;
    while(x){
        mp[fa[x]]=max(mp[fa[x]],++ts[x]);
        if(1.0*mp[x]>=alpha*ts[x])p=x;
        x=fa[x];
    }
    if(p){
        bfs(p);
        mx=inf,all=ts[p],getroot(p);
        fa[root]=fa[p],son[fa[p]].erase(p),son[fa[p]].insert(root);
        build(root);
    }
}
int main(){
    memset(vis,1,sizeof vis);
    for(register int i=1;i<=cnt;++i)pool[i]=i;
    read();
    int n=read(),x,y,node;
    long long ans=0;
    read(),read();
    ts[1]=1,sgt.insert(rt[1],a[1]=read()),puts("0");
    for(register int i=2;i<=n;++i){
        x=read<long long>()^(ans%mod),lct.v[n+i]=y=read(),a[i]=read();
        fa[i]=node=x,son[x].insert(i),sgt.insert(rt[i],a[i]);
        add(i,x,y),add(x,i,y),lct.link(n+i,x),lct.link(i,n+i);
        b[i]=b[x],b[i].push_back(pool[cnt--]);
        for(register int j=b[i].size()-1;node;node=fa[node],--j){
            int dis=lct.Get(i,node);
            ans+=sgt.find(rt[node],dis-a[i])-sgt.find(exc[b[i][j]],dis-a[i]);
            sgt.insert(rt[node],a[i]-dis),sgt.insert(exc[b[i][j]],a[i]-dis);
        }
        printf("%lld\n",ans);
        rebuild(i);
    }
}

Guess you like

Origin www.cnblogs.com/ctz45562/p/11635359.html