bzoj 3435 紫荆花之恋 动态树分治+替罪羊+treap

原创 2016年08月31日 16:42:51

我从未见过如此恶心的树分治。。。。

先动态维护这个树的树分治,当一个子树大小太大时,重构这个点和他的所有子树,用树分治分成平均的子树。

对于一个插入和查询,在树分治结构中从深度高到深度低遍历。然后统计新插入的点过当前中心,到当前分治结构中的路径。
对于一条从 xy 过当前分治中心的路径,设点 x 距当前分治中心的路径长度为 dis(x) 。那么需要满足的条件就是 dis[x]+dis[y]<=r[x]+r[y]
dis[y]r[y]<=r[x]dis[x]

那么对于每个分治中心维护一个平衡树存 dis[x]r[x],对于分治中心的子节点维护存h子树中 dis[x]r[x] 的平衡树。查询时答案加当前分治中心的平衡树中dis[y]r[y]<=r[x]dis[x] 的y的个数减当前分治中心有x的子树的平衡树的中dis[y]r[y]<=r[x]dis[x] 的y的个数。并将这个点插入。

不知道为什么在bz上是TLE的,可能是我写的太挫。

#include <bits/stdc++.h>
using namespace std;
#define N 110000
#define M 15000000
#define ls ch[x][0]
#define rs ch[x][1]
#define ll long long
#define D 51
#define which(x) ch[fa[x]][1]==x
int n,top,r[N];
pair<int,int>st[N];
ll ans;
struct fastio
{
    char getc()
    {
        static const int LEN = 4096;
        static char buf[LEN],*S=buf,*T=buf;
        if(S == T)
        {
            T = (S=buf)+fread(buf,1,LEN,stdin);
            if(S == T)return EOF;
        }
        return *S++;
    }
    int read()
    {
        static char ch;
        static int d;
        while(!isdigit(ch=getc()));
        for(d=ch-'0'; isdigit(ch=getc());)
            d=(d<<3)+(d<<1)+(ch-'0');
        return d;
    }       
}io;
struct graph
{
    int head[N],nex[N<<1],to[N<<1],val[N<<1],tot;
    int fa[N][21],d[N],deep[N];
    void add(int x,int y,int z)
    {
        if(!x||!y)return;
        nex[++tot]=head[x];head[x]=tot;
        to[tot]=y;val[tot]=z;
        if(x>y)
        {
            deep[x]=deep[y]+1;
            fa[x][0]=y;d[x]=d[y]+z;
            for(int i=1;i<=20;i++)
                fa[x][i]=fa[fa[x][i-1]][i-1];
        }
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        for(int i=20;i>=0;i--)
            if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=20;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    int dis(int x,int y)
    {return d[x]+d[y]-2*d[lca(x,y)];}
}g;
struct treap
{
    int ch[M][2],val[M],rnd[M],size[M],fa[M],cnt;
    queue<int>que;
    int ap()
    {
        if(que.empty())return ++cnt;
        int x=que.front();que.pop();
        ls=rs=0;val[x]=0;rnd[x]=0;size[x]=0;fa[x]=0;
        return x;
    }
    void pushup(int x)
    {size[x]=size[ls]+size[rs]+1;}
    int rotate(int x)
    {
        int y=fa[x],k=which(x);

        ch[y][k]=ch[x][k^1];
        ch[x][k^1]=y;
        ch[fa[y]][which(y)]=x;

        fa[x]=fa[y];fa[y]=x;
        fa[ch[y][k]]=y;

        pushup(y);pushup(x);
        return x;
    }
    int insert(int x,int v)
    {   
        if(!x)
        {
            size[x=ap()]=1;
            val[x]=v;rnd[x]=rand()*rand();
            return x;
        }
        if(val[x]>=v)
        {
            ls=insert(ls,v);
            size[x]++;fa[ls]=x;
            if(rnd[ls]>rnd[x])x=rotate(ls);
        }
        else
        {
            rs=insert(rs,v);
            size[x]++;fa[rs]=x;
            if(rnd[rs]>rnd[x])x=rotate(rs);
        }
        return x;
    }
    int query(int x,int v)
    {
        if(!x)return 0;
        if(val[x]<=v)
            return size[ls]+1+query(rs,v);
        else return query(ls,v);
    }
    void del(int x)
    {
        if(!x)return;
        que.push(x);
        del(ls);del(rs);
    }
}tr1;
struct tree_div
{
    int deep[N],fa[N][D],pre[N],rt[N],rt1[N][D];
    int size[N],size1[N][D],f[N],vis[N],root,sum;
    int sta[N][D],tp[N],sta1[D],top1;
    void init()
    {
        f[0]=1<<30;
        for(int i=1;i<=n;i++)
            vis[i]=1;
    }
    void ins(int x,int y)
    {
        for(int i=1;i<=tp[x];i++)
            if(sta[x][i]==y)return;
        sta[x][++tp[x]]=y;
    }
    void del(int x,int y,int v)
    {
        tr1.del(rt[x]),rt[x]=0;
        top1=0;
        for(int i=1,t;i<=tp[x];i++)
        {
            if((t=sta[x][i])>=v)
            {tr1.del(rt1[x][t]);rt1[x][t]=0;}
            else sta1[++top1]=t;
        }
        tp[x]=0;
        for(int i=1;i<=top1;i++)sta[x][++tp[x]]=sta1[i];

        for(int i=g.head[x];i;i=g.nex[i])
            if(g.to[i]!=y&&!vis[g.to[i]])
                del(g.to[i],x,v);
    }
    void dfs1(int x,int y,int t)
    {
        fa[x][deep[t]]=t;
        size[x]=1;
        for(int i=g.head[x];i;i=g.nex[i])
            if(g.to[i]!=y&&!vis[g.to[i]])
                dfs1(g.to[i],x,t),size[x]+=size[g.to[i]];
    }
    void dfs2(int x,int y)
    {
        f[x]=0;
        for(int i=g.head[x];i;i=g.nex[i])
            if(g.to[i]!=y&&!vis[g.to[i]])
                dfs2(g.to[i],x),f[x]=max(f[x],size[g.to[i]]);
        f[x]=max(f[x],sum-size[x]);
        root=f[x] < f[root] ? x:root;
    }
    void dfs3(int x,int y,int &rt,int dis)
    {
        rt=tr1.insert(rt,dis-r[x]);
        for(int i=g.head[x];i;i=g.nex[i])
            if(g.to[i]!=y&&!vis[g.to[i]])
                dfs3(g.to[i],x,rt,dis+g.val[i]);
    }
    void dfs4(int x,int y,int v)
    {
        if(deep[x]<=v)return;
        vis[x]=0;
        for(int i=g.head[x];i;i=g.nex[i])
            if(g.to[i]!=y)
                dfs4(g.to[i],x,v);
    }
    void rebuild(int x,int y)
    {
        dfs1(x,y,y);
        root=0;sum=size[x];
        dfs2(x,y);
        pre[root]=x;deep[root]=deep[y]+1;
        size[root]=sum;size1[x][deep[root]]=sum;

        dfs3(root,0,rt[root],0);
        vis[root]=1;
        for(int t=root,i=g.head[t];i;i=g.nex[i])
            if(g.to[i]!=y&&!vis[g.to[i]])
            {   
                ins(g.to[i],deep[t]);
                dfs3(g.to[i],t,rt1[g.to[i]][deep[t]],g.val[i]);
                rebuild(g.to[i],t);
            }
    }
    ll get(int x,int y,int c,int r)
    {
        top=0;ll ret=0;int org=x;
        g.add(x,y,c);g.add(y,x,c);
        deep[x]=deep[y]+1;pre[x]=x;
        size[x]=1;
        rt[x]=tr1.insert(rt[x],-r);

        for(int i=deep[y],d=c;i>=1;i--)
        {
            fa[org][i]=y;
            d=g.dis(org,y);     
            st[++top]=make_pair(x,y);
            size1[x][i]++;size[y]++;

            ret+=tr1.query(rt[y],r-d);
            ret-=tr1.query(rt1[x][i],r-d);

            rt[y]=tr1.insert(rt[y],d-r);
            rt1[x][i]=tr1.insert(rt1[x][i],d-r);
            ins(x,i);

            x=pre[y];y=fa[x][i-1];
        }
        for(int i=top,t,t1,y;i>=1;i--)
            if((double)size1[st[i].first][deep[st[i].second]]/size[y=st[i].second]>0.80)
            {
                t=fa[t1=pre[y]][deep[y]-1];
                dfs4(t1,t,deep[t]);vis[t]=1;
                del(t1,t,deep[y]);
                rebuild(t1,t);
                break;
            }
        return ret;
    }
}tr2;
int main()
{
    //freopen("ks.in","r",stdin);
    //freopen("ks.out","w",stdout);
    io.read();n=io.read();
    tr2.init();
    for(int i=1,y,c;i<=n;i++)   
    {
        y=io.read();c=io.read();r[i]=io.read();
        ans+=tr2.get(i,y=(y^ans%1000000000),c,r[i]);
        printf("%lld\n",ans);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

BZOJ1119 [POI2009]SLO

一看题就一副置换群的样子……找到循环节,然后假设循环节长度为l,那么如果只在循环节内交换的话,一定每个数至少被计入代价一次,且一共要有2*(l-1)个数被计入答案,显然除了每个数至少一次外剩下的那l-...

[二分图完美匹配必要边 强连通分量] BZOJ 2140 稳定婚姻

求二分图完备匹配的必要边,①存不存在增广环? O(N^2) ②直接试着删去按照hungery找完备匹配 O(N^3)。 如果一个点所在的强连通分量大小大于1,那么说明原图存在一条匹配边-非匹配边-匹配...

BZOJ 3435 Wc2014 紫荆花之恋 动态树分治+替罪羊树+Treap

题目大意:给定一棵树,每次添加一个节点并询问当前有多少点对满足dis(i,j) 吾辈有生之年终于把这道题切了。。。QAQ 什么?你想做这题? 1095切了么?没?去把1095切掉再说! 306...
  • PoPoQQQ
  • PoPoQQQ
  • 2015年03月20日 12:34
  • 3860

[BZOJ3435/UOJ55/WC2014]紫荆花之恋

题目大意 一棵带权树,点 i 与父结点之间的边权为 ci,它的权值为 ri 。每个时刻它会长出一个新的叶子节点,给出这个叶子及父节点的信息,问每次添加新叶子后,树中有多少个点对满足 dist(i,j...

wc2014 紫荆花之恋

替罪羊树套treap,动态点分治维护 我去,分治树连接出向下的边没改。。。。调了我3个小时,真是醉飞了。。。。。 #include #include #include #include #...

【WC2014】紫荆花之恋

【WC2014】紫荆花之恋第二道点分题就切紫荆花之恋真的好吗… 题意: 在一棵树上不断加入一个节点[共n⩽105个n\leqslant10^5个],同时给出{a[在树上的父亲], c[与父亲的距离],...
  • Jazengm
  • Jazengm
  • 2017年04月20日 20:13
  • 259

[替罪羊树 动态标号 线段树] BZOJ 3600 没有人的算术

好题啊 首先肯定是线段树 那么考虑我们怎么比较两个数的大小 采用CLJ在重量平衡树和后缀平衡树在信息学奥赛中的应用中提到的标号思想 不妨令每个节点表示一个区间 用区间的中值代表这个数的大小 具...

BZOJ 3224 Tyvj 1728 普通平衡树(替罪羊树)

拍平…然后…拎起来 替罪羊树传送门 代码来源:kuangbin#include #include #include #include #include #include #include #inc...

[BZOJ3600][没有人的算术][替罪羊树+线段树]

[BZOJ3600][没有人的算术][替罪羊树+线段树]题目大意:定义一种数,要么是0,要么是一个二元组,这个二元组两元都是数。 定义小于是: 0bx = a, y>b,那么(x,y)>(a,b)(...
  • g1n0st
  • g1n0st
  • 2017年02月24日 18:14
  • 136

BZOJ 3224: Tyvj 1728 普通平衡树(替罪羊树)

题意: 替罪羊裸题: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的排名(若有多个相同的数,因输出最小的排名) 4. 查询排名为x的数 5. 求x的前驱...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj 3435 紫荆花之恋 动态树分治+替罪羊+treap
举报原因:
原因补充:

(最多只允许输入30个字)