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

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

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

#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. 随机函数Surprising

    之前写了个用来抽取1-54号的随机函数,发现30-40出现的情况很大,就在果壳上提问了一下//听取了某个大神的建议循环了10000次之后惊喜的发现这样写出现了一大堆相同的数字! 之后有个很神大牛解答了 ...

  2. Bug Tracker

    Bug Tracker 使用笔记(有图有真相)   目的:管理Bug,完善业务流程. 前提条件:BugTracker是基于IIS和SQL Server和Asp.Net的.相当于一个Web端的管理系统. ...

  3. CloudFormation

    亚马逊云服务之CloudFormation   亚马逊的Web Service其实包含了一套云服务.云服务主要分为三种: IaaS: Infrastructure as a service,基础设施即 ...

  4. 企业架构与建模之Archimate视图和视角

    企业架构与建模之Archimate视图和视角 3. ArchiMate的视角与视图 创建.维护一个企业架构是一件非常复杂繁琐的事情,因为这项工作需要面对许多背景.利益各异的干系人,对他们所关注的问题进 ...

  5. 广告基本知识-ROI分解

    任何一个在线广告系统,都面临ROI的问题,对于Invest,我们先不考虑,因为对于流量有多种方式可以买回,也无法优化(当然在RTB的时候是可以优化的).Return是主要优化的方向,Return=点击 ...

  6. ckeditor:复制内容到ckeditor时,只保留文本,忽略其样式解决方法

    打开ckeditor 包下的config.js,在 CKEDITOR.editorConfig= function(config){...}添加一句配置: config.forcePasteAsPla ...

  7. Linux操作系统学习_用户态与内核态之切换过程

    因为操作系统的很多操作会消耗系统的物理资源,例如创建一个新进程时,要做很多底层的细致工作,如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录.页表等,这些操作显然不能随便让任何程序都可以做,于是就产 ...

  8. KingPaper初探 wamp下本地虚拟主机的搭建

    在本地我们进行网站或系统开发时,因为我们本地的地址以localhost为主机名的  我们上传到服务器会有很多东西要修改 为了避免这些不必要的修改,我们可以在本地搭建虚拟主机 一下是在wamp下搭建虚拟 ...

  9. 统计知识选讲(一)——主成分分析(PCA)的思想

    主成分分析的主要目的是希望用较少的变量去解释原来资料中的大部分变异,将我们手中许多相关性很高的变量转化成彼此相互独立或不相关的变量,从而达到降维的目的.在原始数据“预处理”阶段通常要先对它们采用PCA ...

  10. EditPlus配置C环境

    一, 目标 1, 编译 ---- 根据编写的 .c 文件, 生成 .exe 文件 2, 运行 ---- 运行 生成的 .exe文件 3, 清理 ---- 删除 生成的 .exe文件 二, 环境 1,  ...