zoukankan      html  css  js  c++  java
  • bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400

    3435: [Wc2014]紫荆花之恋

    Time Limit: 240 Sec  Memory Limit: 512 MB
    Submit: 159  Solved: 40
    [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

      本来以这道题的写法我是一定不会写题解的,但是这是我AC400,所以还是记录一下吧。

      树的点分治按照归属关系可以建成节点个数n深度log(n)的树,通过在树上维护平衡树来实现点分治,但是本题的加入节点会使整个分治树失衡,所以把他想成是替罪羊树,一旦失衡通过点分治重建整棵子树。

      不知道为什么就我一个人有常数问题。各种inline,register,读入优化,for循环合并,平衡树非递归。。。。。╮(╯▽╰)╭整整两天就砸这题里面了。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    #define MAXN 450000
    #define MAXV MAXN
    #define MAXE MAXV*2
    #define MAXT MAXN*45
    #define INF 0x3f3f3f3f
    #define alpha 0.90
    typedef long long qword;
    const int maxbuf=100000;
    char buf[maxbuf*2];
    char *bufh(buf),*buft(buf+1);
    #define readbuf
    {
            if ((++bufh)==buft)
                    buft=(bufh=buf)+fread(buf,1,maxbuf,stdin);
    }
    #define nextInt(_r_)
    {
            register int _x_=0;
            do
            {
                    readbuf;
            }while (*bufh<'0' || *bufh>'9');
            do
            {
                    _x_=_x_*10+*bufh-'0';
                    readbuf;
            }while (*bufh<='9' && *bufh>='0');
            _r_=_x_;
    }
    /*
    inline int nextInt()
    {
            register char ch;
            register int x=0;
            while (ch=(char)getchar(),ch<'0' || ch>'9');
            while (x=x*10+ch-'0',ch=(char)getchar(),ch>='0' && ch<='9');
            return x;
    }
    */
    int pnt[MAXN],rr[MAXN],fdis[MAXN];
    int VV[MAXT],S[MAXT],L[MAXT],R[MAXT];
    int stack[MAXT];
    int tops;
    inline void init(int n)
    {
            tops=-1;
            int l=min(MAXT,n*50);
            for (register int i=1;i<l;i++)
                    stack[++tops]=MAXT-i;
            return ;
    }
    inline void update(int now)
    {
            S[now]=S[L[now]]+S[R[now]]+1;
    }
    inline void r_rotate(int &now)
    {
            register int t=L[now];
            L[now]=R[t];update(now);
            R[t]=now;update(t);
            now=t;
    }
    inline void l_rotate(int &now)
    {
            register int t=R[now];
            R[now]=L[t];update(now);
            L[t]=now;update(t);
            now=t;
    }
    inline void maintain(int &now)
    {
            if (S[L[L[now]]]>S[R[now]])
            {
                    r_rotate(now);
            //        maintain(L[now]);
            //        maintain(R[now]);
            //        maintain(now);
            }
            if (S[R[R[now]]]>S[L[now]])
            {
                    l_rotate(now);
            //        maintain(L[now]);
            //        maintain(R[now]);
            //        maintain(now);
            }
            if (S[L[R[now]]]>S[L[now]])
            {
                    r_rotate(R[now]);
                    l_rotate(now);
            //        maintain(L[now]);
            //        maintain(R[now]);
            //        maintain(now);
            }
            if (S[R[L[now]]]>S[R[now]])
            {
                    l_rotate(L[now]);
                    r_rotate(now);
            //        maintain(L[now]);
            //        maintain(R[now]);
            //        maintain(now);
            }
    }
    int *st[MAXN];
    void Insert(int &now,int v)
    {
            register int *nn;
            register int tops2=-1;
            if (!now)
            {
                    nn=&now;
            }else
            {
                    st[++tops2]=&now;
                    while (true)
                    {
                            if (v<=VV[*st[tops2]])
                            {
                                    if (!L[*st[tops2]])
                                    {
                                            nn=&L[*st[tops2]];
                                            break;
                                    }
                                    st[tops2+1]=&L[*st[tops2]];tops2++;
                            }
                            else
                            {
                                    if (!R[*st[tops2]])
                                    {
                                            nn=&R[*st[tops2]];
                                            break;
                                    }
                                    st[tops2+1]=&R[*st[tops2]];tops2++;
                            }
                    }
            }
            *nn=stack[tops--];
            if (L[*nn])stack[++tops]=L[*nn];
            if (R[*nn])stack[++tops]=R[*nn];
            VV[*nn]=v;
            S[*nn]=1;
            L[*nn]=R[*nn]=0;
            while (~tops2)
            {
                    update(*st[tops2]);
                    maintain(*st[tops2--]);
            }
    }
    int Get_rank2(register int now,int v)
    {
            register int ret=0;
            while (now)
            {
                    if (v<=VV[now])
                    {
                            ret+=S[R[now]]+1;
                            now=L[now];
                    }
                    else
                            now=R[now];
            }
            return ret;
    }
    void Scan(int &now)
    {
            if (!now)return ;
            Scan(L[now]);
            printf("%d ",VV[now]);
            Scan(R[now]);
    }
    struct Edge
    {
            int np,val;
            int lev;
            Edge *next,*neg;
    }E[MAXE],*V[MAXV];
    int tope=-1;
    inline void addedge(int x,int y,int z)
    {
            E[++tope].np=y;
            E[tope].next=V[x];
            E[tope].val=z;
            V[x]=&E[tope];
    }
    int rdis[MAXN],jump[18][MAXN];
    int depth[MAXN];
    inline int lca(int x,int y)
    {
            if (depth[x]<depth[y])swap(x,y);
            int dep=depth[x]-depth[y];
            for (register int i=0;i<18;i++)
                    if (dep & (1<<i))
                            x=jump[i][x];
            if (x==y)return x;
            for (register int i=17;i>=0;i--)
                    if (jump[i][x]!=jump[i][y])
                            x=jump[i][x],y=jump[i][y];
            return pnt[x];
    }
    inline int dis(int x,int y)
    {
            return rdis[x]+rdis[y]-2*rdis[lca(x,y)];
    }
    struct sct_edge
    {
            sct_edge *next;
            int np;
            int root;
    }sct[MAXN*5],*sctv[MAXN];
    int topse=-1;
    int scp[MAXN];
    sct_edge* scpe[MAXN];
    int scroot[MAXN];
    int sctlev[MAXN];
    int sctsiz[MAXN];
    inline void sct_addedge(int x,int y)
    {
            sct[++topse].np=y;
            sct[topse].next=sctv[x];
            sctv[x]=&sct[topse];
    }
    int q[MAXN];
    int pntt[MAXN];
    int siz[MAXN];
    int find_core(register int now)
    {
            register int head=-1,tail=0;
            register Edge *ne;
            q[0]=now;
            pntt[now]=now;
            while (head<tail)
            {
                    now=q[++head];
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pntt[now] || ~ne->lev)continue;
                            q[++tail]=ne->np;
                            pntt[ne->np]=now;
                    }
            }
            int bstsiz=INF,core=-1;
            for (register int i=tail;i>=0;i--)
            {
                    now=q[i];
                    siz[now]=1;
                    int mxsiz=0;
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pntt[now] || ~ne->lev)continue;
                            siz[now]+=siz[ne->np];
                            mxsiz=max(mxsiz,siz[ne->np]);
                    }
                    mxsiz=max(mxsiz,(tail+1)-siz[now]);
                    if (bstsiz>mxsiz)
                    {
                            bstsiz=mxsiz;
                            core=now;
                    }
            }
            return core;
    }
    int dstt[MAXN];
    void dfs2(register int now,int ds,int p,int &r1,int &r2,int lv)
    {
            register int head=-1,tail=0;
            register Edge *ne;
            q[0]=now;
            dstt[now]=ds;
            pntt[now]=p;
            while (head<tail)
            {
                    now=q[++head];
                    Insert(r1,rr[now]-dstt[now]);
                    Insert(r2,rr[now]-dstt[now]);
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->lev<lv || ne->np==pntt[now])continue;
                            pntt[ne->np]=now;
                            q[++tail]=ne->np;
                            dstt[ne->np]=dstt[now]+ne->val;
                    }
    
            }
    }
    int solve(int root,int lv)
    {
            register int core=find_core(root);
            register Edge *ne;
            sctlev[core]=lv;
            Insert(scroot[core],rr[core]-0);
            sctsiz[core]=siz[root];
            if (siz[root]==1)
                    return core;
            for (ne=V[core];ne;ne=ne->next)
            {
                    if (~ne->lev)continue;
                    ne->lev=ne->neg->lev=lv;
                    int t;
                    sct_addedge(core,t=solve(ne->np,lv+1));
                    scp[t]=core;
                    scpe[t]=sctv[core];
                    dfs2(ne->np,ne->val,core,scpe[t]->root,scroot[core],lv);
            }
            return core;
    }
    void sct_rebuild(register int now)
    {
            int head=-1,tail=0;
            int lv=sctlev[now];
            register sct_edge* ns;
            register Edge *ne;
            q[0]=now;
            while (head<tail)
            {
                    now=q[++head];
                    for (ns=sctv[now];ns;ns=ns->next)
                            q[++tail]=ns->np;
                    sctv[now]=0;
            }
            head=-1,tail=0;
            now=q[0];
            pntt[now]=now;
            while (head<tail)
            {
                    now=q[++head];
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pntt[now] || ne->lev<lv)continue;
                            pntt[ne->np]=now;
                            ne->lev=ne->neg->lev=-1;
                            q[++tail]=ne->np;
                    }
            }
            int pt;
            sct_edge *pe;
            now=q[0];
            pe=scpe[now],pt=scp[now];
            for (int i=0;i<=tail;i++)
            {
                    now=q[i];
                    if (i && scpe[now]->root)
                            stack[++tops]=scpe[now]->root;
                    if (scroot[now])
                            stack[++tops]=scroot[now];
                    scroot[now]=0;
                    if (scpe[now])
                            scpe[now]=NULL;
            }
            now=solve(now,sctlev[q[0]]);
            //core->now
            if (pe)
                    pe->np=now;
            scpe[now]=pe;
            scp[now]=pt;
    }
    
    int main()
    {
            freopen("input.txt","r",stdin);
            freopen("output.txt","w",stdout);
            int x,n;
            /*
               int root=0;
               for (int i=1;i<100;i++)
               {
               Insert(root,rand()%1000);
               Scan(root);printf("
    ");
               }
               return 0;*/
            nextInt(x);
            qword ans=0;
            nextInt(n);
            init(n);
            int rebuild_pos;
            for (int i=1;i<=n;i++)
            {
                    nextInt(pnt[i]);
                    nextInt(fdis[i]);
                    nextInt(rr[i]);
                    //scanf("%d%d%d",&pnt[i],&fdis[i],&rr[i]);
                    //printf("%d
    ",i);
                    pnt[i]^=(int)(ans%1000000000);
                    if (i==1)
                    {
                            scp[i]=0;
                            scpe[i]=NULL;
                            sctlev[i]=1;
                            Insert(scroot[i],rr[i]-0);
                            sctsiz[i]=1;
                    }else
                    {
                            rdis[i]=rdis[pnt[i]]+fdis[i];
                            depth[i]=depth[pnt[i]]+1;
                            jump[0][i]=pnt[i];
                            for (register int j=1;j<18;j++)
                                    jump[j][i]=jump[j-1][jump[j-1][i]];
                            scp[i]=pnt[i];
                            sct_addedge(pnt[i],i);
                            sctlev[i]=sctlev[scp[i]]+1;
                            addedge(pnt[i],i,fdis[i]);
                            addedge(i,pnt[i],fdis[i]);
                            V[i]->neg=V[pnt[i]];V[pnt[i]]->neg=V[i];
                            V[i]->lev=V[pnt[i]]->lev=sctlev[pnt[i]];
                            scpe[i]=sctv[pnt[i]];
                            register sct_edge* ns;
                            sctsiz[i]++;
                            int d;
                            rebuild_pos=-1;
                            Insert(scroot[i],rr[i]-0);
                            for (ns=scpe[i],x=scp[i],d=fdis[i];ns;ns=scpe[x],x=scp[x],d=dis(i,x))
                            {
                                    //    printf("[+]");Scan(scroot[x]);printf("
    ");
                                    //    printf("[-]");Scan(ns->root);printf("
    ");
                                    //    printf("[F]%d
    ",d-rr[i]);
                                    ans+=Get_rank2(scroot[x],d-rr[i])-Get_rank2(ns->root,d-rr[i]);
                                    Insert(scroot[x],rr[i]-d);
                                    Insert(ns->root,rr[i]-d);
                                    sct_edge *ns2;
                                    sctsiz[x]++;
                                    for (ns2=sctv[x];ns2;ns2=ns2->next)
                                    {
                                            if (sctsiz[ns2->np]>sctsiz[x]*alpha)
                                                    rebuild_pos=x;
                                    }
                            }
                            //sct_rebuild(rand()%i+1);
                            if (~rebuild_pos)
                                    sct_rebuild(rebuild_pos);
                    }
                    printf("%lld
    ",ans);
            }
    }

    `

    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    用 ArcMap 发布 ArcGIS Server FeatureServer Feature Access 服务 PostgreSQL 版本
    ArcMap 发布 ArcGIS Server OGC(WMSServer,MapServer)服务
    ArcScene 创建三维模型数据
    ArcMap 导入自定义样式Symbols
    ArcMap 导入 CGCS2000 线段数据
    ArcMap 导入 CGCS2000 点坐标数据
    ArcGis Server manager 忘记用户名和密码
    The view or its master was not found or no view engine supports the searched locations
    python小记(3)操作文件
    pytest(2) pytest与unittest的区别
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4328648.html
Copyright © 2011-2022 走看看