每插入一个点,直接把它当做重心插入原树,当做是动态点分树一样维护

但这样深度会越来越大,所以我们用类似替罪羊的方法

当树失去平衡时,对子树进行一次点分,保证复杂度

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
using namespace std;
typedef long long LL;
const int M=100007;
const int N=M*80;
double alpha=0.7;
inline int rd(){
    int x=0;bool f=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=0;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x;
}

LL w[M];

struct Pool{
    int mempool[N],tot;
    Pool(){
        for(int i=1;i<N;i++) mempool[i]=i;
        tot=0;
    }
    int newmem(){
        return mempool[++tot];
    }
    int delmem(int x){
        mempool[tot--]=x;
    }
}pool1,pool2,pool3;

int g[M],te;
struct edge{
    int y,next;
    LL d;
}e[M<<1];
void addedge(int x,int y,LL d){
    e[++te].y=y;
    e[te].d=d;
    e[te].next=g[x];
    g[x]=te;
}

struct uppp{//不同于前两题,all放在外面维护了
//多维护点分root(fa)+在fa的哪个儿子的子树下(fson)
    int sub;
    int fa,fson;
    LL dis;
    int next;
}up[N];
int hd[M],tu;
void addup(int x,int sub,int fa,int fson,LL dis){
    tu=pool1.newmem();
    up[tu].sub=sub;
    up[tu].fa=fa;
    up[tu].fson=fson;
    up[tu].dis=dis;
    up[tu].next=hd[x];
    hd[x]=tu;
}

int n;
int idsub,idrt,ifa,ifson;
int all[M];//子树信息,动态维护点分树的话这样写方便
int que[M];

int T=0;
int vis[M],sz[M];
int size,mi,rt;

int lc[N],rc[N],cnt[N],fix[N];
LL val[N];
struct treap{
    int siz,root;
    treap(){siz=root=0;}
    void del(int x){
        if(!x) return;
        pool2.delmem(x);
        del(lc[x]);
        del(rc[x]);
    }
    void delet(){
        del(root);
        root=0;
        siz=0;
    }
    int newnode(LL d){
        int x=pool2.newmem();
        lc[x]=rc[x]=0;
        cnt[x]=1;
        val[x]=d;
        fix[x]=rand();
        return x;
    }
    void update(int x){
        cnt[x]=1;
        if(lc[x]) cnt[x]+=cnt[lc[x]];
        if(rc[x]) cnt[x]+=cnt[rc[x]];
    }
    void rotl(int &x){
        int k=rc[x];
        rc[x]=lc[k];
        lc[k]=x;
        update(x);
        update(k);
        x=k;
    }
    void rotr(int &x){
        int k=lc[x];
        lc[x]=rc[k];
        rc[k]=x;
        update(x);
        update(k);
        x=k;
    }
    void insert(int &x,LL d){
        if(!x){
            x=newnode(d);
            return;
        }
        cnt[x]++;
        if(d<=val[x]){
            insert(lc[x],d);
            if(fix[lc[x]]<fix[x])rotr(x);
        }
        else{
            insert(rc[x],d);
            if(fix[rc[x]]<fix[x])rotl(x);
        }
    }
    void ins(LL d){
        insert(root,d);
        siz++;
    }
    int query(int x,LL d){
        if(!x) return 0;
        if(d<val[x]) return query(lc[x],d);
        return cnt[lc[x]]+1+query(rc[x],d);
    }
    LL get(LL d){
        return query(root,d);
    }
}a[N];

void clear(int x,int fa){
    int p,y;

    p=hd[x];

    //清空treap时每个点把它到父亲那两个treap清空就可以了
    if(p&&vis[up[p].fa]!=T){
        a[up[p].sub].delet();
        pool3.delmem(up[p].sub);
    }
    a[all[x]].delet();
    pool3.delmem(all[x]);

    //把需要清的静链清掉
    for(p=hd[x];p&&vis[up[p].fa]!=T;p=up[p].next)
        pool1.delmem(p);
    hd[x]=p;

    for(p=g[x];p;p=e[p].next)
    if(vis[y=e[p].y]!=T&&y!=fa){
        clear(y,x);
    }
}

void getsz(int x,int fa){
    sz[x]=1;
    int p,y;
    for(p=g[x];p;p=e[p].next)
    if(vis[y=e[p].y]!=T&&y!=fa){
        getsz(y,x);
        sz[x]+=sz[y];
    }
}

void getrt(int x,int fa){
    int f,p,y;
    f=size-sz[x];
    for(p=g[x];p;p=e[p].next)
    if(vis[y=e[p].y]!=T&&y!=fa){
        getrt(y,x);
        f=max(f,sz[y]);
    }
    if(f<mi) mi=f,rt=x;
}

void dfs(int x,int fa,LL dis){
    addup(x,idsub,ifa,ifson,dis);
    a[idrt].ins(dis-w[x]);
    a[idsub].ins(dis-w[x]);
    int p,y;
    for(p=g[x];p;p=e[p].next)
        if(vis[y=e[p].y]!=T&&y!=fa) dfs(y,x,dis+e[p].d);
}

void work(int frm){
    getsz(frm,0);
    mi=size=sz[frm];
    getrt(frm,0);
    int x=rt,p,y;
    vis[x]=T;
    ifa=x;
    all[x]=idrt=pool3.newmem();
    a[all[x]].ins(-w[x]);
    for(p=g[x];p;p=e[p].next)
    if(vis[y=e[p].y]!=T){
        idsub=pool3.newmem();
        ifson=y;
        dfs(y,x,e[p].d);
    }
    for(p=g[x];p;p=e[p].next)
        if(vis[y=e[p].y]!=T) work(y);
}

void rebuild(int x){
    clear(x,0);
    work(x);
}

void link(int x,int y,LL d){
    if(y==0){
        all[x]=pool3.newmem();
        a[all[x]].ins(-w[x]);
        return;
    }

    addedge(x,y,d);
    addedge(y,x,d);

    int p;
    //暴力插入
    all[x]=pool3.newmem();
    a[all[x]].ins( -w[x] );

    int tmpt=0;
    for(p=hd[y];p;p=up[p].next) que[++tmpt]=p;
    for(int i=tmpt;i>0;i--){//保证链的搜索顺序还是从下到上
        p=que[i];
        addup(x,up[p].sub,up[p].fa,up[p].fson,d+up[p].dis);
        a[all[up[p].fa]].ins( d+up[p].dis-w[x] );
        a[up[p].sub].ins( d+up[p].dis-w[x] );
    }
    //x-y
    int nw=pool3.newmem();
    addup(x,nw,y,x,d);
    a[all[y]].ins( d-w[x] );
    a[nw].ins( d-w[x] );

    //判断是否要重构
    int reb=0;
    for(p=hd[y];p;p=up[p].next){
        if((double)a[all[up[p].fa]].siz*alpha<(double)a[up[p].sub].siz)
            reb=up[p].fa;
    }

    if(reb){
        T++;//时间戳
        for(p=hd[reb];p;p=up[p].next)//***
            vis[up[p].fa]=T;
        rebuild(reb);
    }

}

LL get(int x){
    LL res=a[all[x]].get(w[x]);
    for(int p=hd[x];p;p=up[p].next){
        res+=a[all[up[p].fa]].get(w[x]-up[p].dis);
        res-=a[up[p].sub].get(w[x]-up[p].dis);
    }
    return res;
}

int main(){
    int i,x,y,z,tt;
    LL res=0;
    n=rd();//滤掉测试点
    n=rd();
    for(i=1;i<=n;i++){
        tt=res%1000000000;
        x=rd()^tt;
        y=rd();
        w[i]=rd();
        link(i,x,y);
        res+=get(i)-1;
        printf("%lld\n",res);
    }
    return 0;
}

uoj 55 紫荆花之恋 动态点分治+替罪羊式重构+treap的更多相关文章

  1. BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

  2. luoguP3920 [WC2014]紫荆花之恋 动态点分治 + 替罪羊树

    意外的好写..... 考虑点分 \(dis(i, j) \leq r_i + r_j\) 对于过分治中心一点\(u\),有 \(dis(i, u) - r_i = dis(j, u) + r_j\) ...

  3. UOJ #55 & 洛谷 P3920 紫荆花之恋 —— 动态点分治+替罪羊树

    题目:http://uoj.ac/problem/55 https://www.luogu.org/problemnew/show/P3920 参考博客:https://www.cnblogs.com ...

  4. [WC2014]紫荆花之恋(动态点分治+替罪羊思想)

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

  5. [WC2018]即时战略——动态点分治(替罪羊式点分树)

    题目链接: [WC2018]即时战略 题目大意:给一棵结构未知的树,初始时除1号点其他点都是黑色,1号点是白色,每次你可以询问一条起点为白色终点任意的路径,交互库会自动返回给你这条路径上与起点相邻的节 ...

  6. UOJ#55. 【WC2014】紫荆花之恋 点分树 替罪羊树 平衡树 splay Treap

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ55.html 题解 做法还是挺容易想到的. 但是写的话…… 首先这种题如果只要求一棵树中的满足条件的点数( ...

  7. bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)

    传送门(权限) 传送门(非权限) 题解 我终终终终终终于做出来啦!!! 作为一个没有学过替罪羊树的蒟蒻现场学了一下替罪羊树,作为一个平衡树都写数组版本的看着大佬的指针题解无语只能硬去理解然后照着抄了一 ...

  8. 【WC2014】紫荆花之恋(替罪羊重构点分树 & 平衡树)

    Description 若带点权.边权的树上一对 \((u, v)\) 为 friend,那么需要满足 \(\text{dist}(u, v) \le r_u + r_v\),其中 \(r_x\) 为 ...

  9. UOJ#55. 【WC2014】紫荆花之恋

    传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...

随机推荐

  1. 基本功能的shell

    手把手教你编写一个具有基本功能的shell(已开源) 刚接触Linux时,对shell总有种神秘感:在对shell的工作原理有所了解之后,便尝试着动手写一个shell.下面是一个从最简单的情况开始,一 ...

  2. (转)C++重写、重载和重定义的区别

    C++ 重写重载重定义区别 (源自:http://blog.163.com/clevertanglei900@126/blog/static/111352259201102441934870/) 1 ...

  3. sql基础篇

    再跟SQL谈一谈--基础篇   1.简介 2.DDL & DML 3.SELECT ①DISTINCT ②WHERE ③AND & OR ④ORDER BY 4.INSERT 5.UP ...

  4. EasyUI Editable Tree

    效果如图: Create Tree <ul id="tt"></ul> $('#tt').etree({ url: 'tree_data.json', cr ...

  5. 我的TDD实践---UnitTest单元测试

    我的TDD实践---UnitTest单元测试 “我的TDD实践”系列之UnitTest单元测试 写在前面: 我的TDD实践这几篇文章主要是围绕测试驱动开发所展开的,其中涵盖了一小部分测试理论,更多的则 ...

  6. 一步一步深入spring(1)--搭建和测试spring的开发环境

    1.引用jar包 到spring的网站上下载spring的jar包(本文是2.5.6),解压缩后找到 使用spring必须引用的jar包 spring.jar  commons-logging.jar ...

  7. Tapestry5.3使用总结

    1.Tapestry框架的加载是通过Filter来完成的,需要在web.xml中加入以下配置: <filter> <filter-name>app</filter-nam ...

  8. There is no getter for property named 'userSpAndSp' in 'class com.uauth.beans.UserSpAndSp'

    mybatis 报错There is no getter for property named 'userSpAndSp' in 'class com.uauth.beans.UserSpAndSp' ...

  9. 背水一战 Windows 10 (38) - 控件(布局类): Panel, Canvas, RelativePanel, StackPanel, Grid

    [源码下载] 背水一战 Windows 10 (38) - 控件(布局类): Panel, Canvas, RelativePanel, StackPanel, Grid 作者:webabcd 介绍背 ...

  10. trie树模板(统计难题)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submi ...