【 [Wc2014]紫荆花之恋】(⊙o⊙)动态点分治重构

久闻紫荆花之恋大名,今日一见,果然名不虚传,不过名字确实挺美的owo luogu3920 UOJ55  

3435: [Wc2014]紫荆花之恋

Time Limit: 240 Sec  Memory Limit: 512 MB Submit: 688  Solved: 235 [Submit][Status][Discuss]

Description

强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这个大树实际上是一个带权树。每个时刻它会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + R! ,其中 dist(i, j)表示在这个树上从 i 到 j 的唯一路径上所有边的边权和。强强和萌萌很好奇每次新长出一个叶子节点之后,这个树上总共有几对朋友。 我们假定这个树一开始为空,节点按照加入的顺序从 1开始编号。由于强强非常好奇, 你必须在他每次出现新节点后马上给出总共的朋友对数,不能拖延哦。

Input

共有 n + 2 行。 第一行包含一个正整数,表示测试点编号。 第二行包含一个正整数 n ,表示总共要加入的节点数。 我们令加入节点前的总共朋友对数是 last_ans,在一开始时它的值为0。 接下来 n 行中第 i 行有三个数 ai, bi, ri,表示节点  i  的父节点的编号为 ai xor (last_ans mod 10^9)   (其中xor 表示异或,mod  表示取余,数据保证这样操作后得到的结果介于 1到i  –  1之间),与父节点之间的边权为 ci,节点 i 上小精灵的感受能力值为r!。 注意 a1 = c1 = 0,表示 1 号点是根节点,对于 i > 1,父节点的编号至少为1。

Output

包含 n 行,每行输出1 个整数, 表示加入第 i 个点之后,树上有几对朋友。

Sample Input

0 5 0 0 6 1 2 4 0 9 4 0 5 5 0 2 4

Sample Output

  0 1 2 4 7

HINT

1<=Ci<=10000 Ai<=2*10^9 Ri<=10^9 N<=100000 我们发现有万恶之源--强制在线,我们如果不强制在线,就是一个套路的动态点分治了,同样每个点维护自己子树信息和到该子树到父亲的信息,对于lcax来说就是因为disi + disj<= ri + rj,也就是disi - ri <= rj - disj,我们把disi - ri加入平衡树里面,然后查询的时候查询rj - disj 的排名就可以了,但是,但是,但是orz。 好吧,这里我们就要用到替罪羊的思想了,不平衡就重构。就是把他管的那一颗点分子树信息全部消除,然后一个点分树新建,找重心,加入距离,恩,看上去似乎还好,也没什么。 只有自己调试的时候痛苦不已。我之前写的时候居然平衡树替罪羊一直重构都没起到作用,也就是说一直是不平衡树,居然能拿到90,,加上大家都说卡常,我还以为常数痴了,一直在卡常。没想到啊orz。 7500B LJ代码:
#include<stdio.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
//
int JSCNT;
namespace bz{
    const int maxn = 100005;
    int fa[17][maxn],dep[maxn];ll dis[maxn];
    int glca(int x,int y) {
        if(dep[x]<dep[y]) swap(x,y);
        int dd = dep[x] - dep[y];
        for(int i=0;dd;i++,dd>>=1)
            if(dd&1) x = fa[i][x];
        if(x==y) return x;
        for(int i=16;i>=0;i--)
            if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
        return fa[0][x];
    }
    ll gdis(int x,int y) {
        int lcc = glca(x,y);
        return dis[x] + dis[y] - 2*dis[lcc];
    }
    void add(int x,int f,int C) {
        dep[x] = dep[f] + 1; fa[0][x] = f; dis[x] = dis[f] + C;
        for(int i=1;i<=16;i++) fa[i][x] = fa[i-1][fa[i-1][x]];
    }
}
//
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline ll _R()
{
    char t=GC;
    ll x=0;
    while(!isdigit(t)) t=GC;
    while(isdigit(t)) x=x*10+t-48,t=GC;
    return x;
}
char pbuf[1<<20],*pp=pbuf;
void push(const char c) {
    if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
    *pp++=c;
}
inline void _W(ll x) {
    static int sta[35];
    int top=0;
    do{sta[top++]=x%10,x/=10;}while(x);
    while(top) push(sta[--top]+'0');
    push('\n');
}

//
namespace bt{
    const int maxn = 4000005;
    struct node{
        node *ls,*rs;ll dat;int siz,ct;ll mx;
    }z[maxn],*nul,*pool[maxn],**RT; int lj,tot;
    void upd(node *&p) {
           p->siz = p->ls->siz + p->rs->siz + p->ct;
        p->mx = p->dat;
        if(p->ls!=nul) p->mx = max(p->ls->mx,p->mx);
        if(p->rs!=nul) p->mx = max(p->rs->mx,p->mx);
    }
    vector<int>ve[maxn];
    bool isbad(node *&p) {
        if(max(p->ls->siz,p->rs->siz)>p->siz*0.88) return 1;
        return 0;
    }
    node* nwnode(int x) {
        node *p = lj?pool[lj--]:&z[++tot];
        p->ls = p->rs = nul; p->siz = p->ct = 1; p->dat = p->mx = x;
        return p;
    }
    void ins(node *&p,int x) {
        if(p==nul) {
            p = nwnode(x);
            return ;
        }
        if(x==p->dat) p->ct++;
        else if(x<p->dat) ins(p->ls,x);
        else ins(p->rs,x);
        if(isbad(p)) RT = &p;
        upd(p);
    }
    ll lower(node*&p,ll x) {
        if(p==nul) return 0;
        if(p->mx<=x) return p->siz;
        if(p->dat==x) return p->ls->siz + p->ct;
        if(p->dat<x) return p->ls->siz + p->ct + lower(p->rs,x);
        return lower(p->ls,x);
    }
    void init() {
        nul=z; nul->ls=nul->rs=nul;
    }
    int stad[maxn],stac[maxn],tp;
    void tra(node *&p) {
        if(p==nul) return;
        tra(p->ls);
        ++tp;
        stad[tp] = p->dat; stac[tp]=p->ct;
        pool[++lj]=p;
        tra(p->rs);
    }
    void build(node *&p,int l,int r) {
        int mid = (l+r)>>1;
        p = nwnode(stad[mid]);
        p->ct = p->siz = stac[mid];
        if(l<mid) build(p->ls,l,mid-1);
        if(mid<r) build(p->rs,mid+1,r);
        upd(p);
    }
    void rebuild() {
        tp=0;
        tra(*RT);
        build(*RT,1,tp);
        RT = &nul;
    }
    node *sont[maxn],*treet[maxn]; //  sont --> to father treet --> to it
    void add(node *&p,int x) {
        RT = &nul;
        ins(p,x);
        if(*RT!=nul) rebuild();
    }
    void clr(node *&p) {
        tp = 0;
        tra(p);
        p = nul;
    }
}//
int n;
namespace dft{
    const int maxn = 300005;
    int r[maxn];
    int la[maxn],owo,en[maxn],nt[maxn],len[maxn];
    int vis[maxn],vivi[maxn],tim;
    void adg(int x,int y,int le) {
        en[++owo]=y; nt[owo]=la[x]; la[x]=owo; len[owo]=le;
        en[++owo]=x; nt[owo]=la[y]; la[y]=owo; len[owo]=le;
    }
    vector<int>sons[maxn];
    int fa[maxn],VV;
    void fuckall(int x) {
        vis[x] = tim;
        bt::clr(bt::treet[x]);
        for(auto y:sons[x]) {
            if(fa[y]!=x) continue;
            fuckall(y);
            bt::clr(bt::sont[y]);
        }
        sons[x].clear();
    }
    int rtsz,rrt,sm,sz[maxn];
    void gsi(int x,int ba) {
        sz[x]=1;
        for(int it=la[x];it;it=nt[it]){
            int y = en[it];
            if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
            gsi(y,x); sz[x] += sz[y];
        }
    }
    void grt(int x,int ba) {
        int sso = 0;
        for(int it=la[x];it;it=nt[it]) {
            int y = en[it];
            if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
            grt(y,x); sso = max(sso,sz[y]);
        }
        sso = max(sso,sm-sz[x]);
        if(sso<rtsz) rtsz=sso,rrt=x;
    }
    void insdeep(int x,int ba,ll dd) {
        bt::stad[++bt::tp]=dd-r[x];
        for(int it=la[x];it;it=nt[it]) {
            int y = en[it];
            if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
            insdeep(y,x,dd+len[it]);
        }
    }
    void jianli(bt::node *&p) {
        if(!bt::tp) return;
        sort(bt::stad+1,bt::stad+1+bt::tp);
        int now = 1; bt::stac[1] = 1;
        for(int i=2;i<=bt::tp;i++) {
            if(bt::stad[i]==bt::stad[now]) bt::stac[now]++;
            else bt::stad[++now]=bt::stad[i],bt::stac[now]=1;
        }
        bt::build(p,1,now);
    }
    void DC(int x) {
        vivi[x] = tim;
        bt::tp = 0;
        insdeep(x,0,0);
        jianli(bt::treet[x]);
        for(int it=la[x];it;it=nt[it]) {
            int y = en[it];
            if(vis[y]!=tim||vivi[y]==tim) continue;
            gsi(y,x); sm=sz[y]; rtsz=0x3f3f3f3f;
            grt(y,x); int p = rrt;
            bt::tp = 0;
            insdeep(y,x,len[it]);
            jianli(bt::sont[p]);
            DC(p); fa[p] = x;
            sons[x].push_back(p);
        }
    }
    int FRT=1;
    void rebuild(int x) {
        int ff = fa[x];
        ++tim;
        bt::node* p = bt::sont[x];
        bt::sont[x]= bt::nul;
        fuckall(x);
        gsi(x,0);
        sm = sz[x]; rtsz=0x3f3f3f3f;
        grt(x,0);
        x = rrt;
        bt::sont[x]=p;
        zz:DC(x);
        if(ff)sons[ff].push_back(x);
        fa[x] = ff;
        FRT = x;
    }
    int insert(int x,int f) {
        bt::sont[x] = bt::nul; bt::treet[x] = bt::nul;

        ll ans = 0;

        sons[f].push_back(x);
        fa[x] = f; ll dd,d=0;
        for(int p=x;p;p=fa[p]) {
            dd = d;
            if(fa[p]) {
                d = bz::gdis(x,fa[p]);
                ans += bt::lower(bt::treet[fa[p]],r[x]-d);
                ans -= bt::lower(bt::sont[p],r[x]-d);
                bt::add(bt::sont[p],d-r[x]);
            }
            // dd = bz::gdis(x,p);
            bt::add(bt::treet[p],dd-r[x]);		
        }
        
        int rere = 0;
        for(int p=x;fa[p];p=fa[p]) {
            if(bt::treet[p]->siz>bt::treet[fa[p]]->siz*0.88)  rere = fa[p];
        }
        
        if(rere)rebuild(rere);
        return ans;
    }
}
int main() {
//	freopen("aa.in","r",stdin);
    bt::init();
    int ozozoz;
    ozozoz=_R();n=_R();
    ll lastans = 0;
    for(int i=1;i<=n;i++) {
        ll A,C,R; A=_R();C=_R();R=_R();
        dft::r[i] = R;
        A^=(int)(lastans%((long long)1e9));
        if(A!=0)bz::add(i,A,C); if(A!=0)dft::adg(i,A,C);
        lastans += dft::insert(i,A);
        _W(lastans);
    } 
    fwrite(pbuf,1,pp-pbuf,stdout);
 //   cout<<JSCNT;
}
 
posted @ 2018-12-22 10:22  Newuser233  阅读(9)  评论(0)    收藏  举报