uoj 55 紫荆花之恋 动态点分治+替罪羊式重构+treap
每插入一个点,直接把它当做重心插入原树,当做是动态点分树一样维护
但这样深度会越来越大,所以我们用类似替罪羊的方法
当树失去平衡时,对子树进行一次点分,保证复杂度
#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的更多相关文章
- BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- luoguP3920 [WC2014]紫荆花之恋 动态点分治 + 替罪羊树
意外的好写..... 考虑点分 \(dis(i, j) \leq r_i + r_j\) 对于过分治中心一点\(u\),有 \(dis(i, u) - r_i = dis(j, u) + r_j\) ...
- UOJ #55 & 洛谷 P3920 紫荆花之恋 —— 动态点分治+替罪羊树
题目:http://uoj.ac/problem/55 https://www.luogu.org/problemnew/show/P3920 参考博客:https://www.cnblogs.com ...
- [WC2014]紫荆花之恋(动态点分治+替罪羊思想)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- [WC2018]即时战略——动态点分治(替罪羊式点分树)
题目链接: [WC2018]即时战略 题目大意:给一棵结构未知的树,初始时除1号点其他点都是黑色,1号点是白色,每次你可以询问一条起点为白色终点任意的路径,交互库会自动返回给你这条路径上与起点相邻的节 ...
- UOJ#55. 【WC2014】紫荆花之恋 点分树 替罪羊树 平衡树 splay Treap
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ55.html 题解 做法还是挺容易想到的. 但是写的话…… 首先这种题如果只要求一棵树中的满足条件的点数( ...
- bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)
传送门(权限) 传送门(非权限) 题解 我终终终终终终于做出来啦!!! 作为一个没有学过替罪羊树的蒟蒻现场学了一下替罪羊树,作为一个平衡树都写数组版本的看着大佬的指针题解无语只能硬去理解然后照着抄了一 ...
- 【WC2014】紫荆花之恋(替罪羊重构点分树 & 平衡树)
Description 若带点权.边权的树上一对 \((u, v)\) 为 friend,那么需要满足 \(\text{dist}(u, v) \le r_u + r_v\),其中 \(r_x\) 为 ...
- UOJ#55. 【WC2014】紫荆花之恋
传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...
随机推荐
- oracle数据库管理--对象、角色相关查询
1.数据字典: 记录了数据库的系统信息,它是只读表和视图的集合,数据字典的所有用户者为sys用户.用户只能在数据字典上执行查询操作(select语句),而其维护与修改是由系统自动完成的.数据字 ...
- 随机函数Surprising
之前写了个用来抽取1-54号的随机函数,发现30-40出现的情况很大,就在果壳上提问了一下//听取了某个大神的建议循环了10000次之后惊喜的发现这样写出现了一大堆相同的数字! 之后有个很神大牛解答了 ...
- 算法打基础——符号&递归解法
第二节 算法复杂度分析的的基本符号及 递归关系式下的复杂度解法 这次的主要知识点是: 1.各种复杂度符号 2.递归复杂度解法: 分为三种 替换法(猜!) 递归树法 主定理 1各种复杂度符号 ...
- .NET并行计算基本介绍、并行循环使用模式
.NET并行计算基本介绍.并行循环使用模式) 阅读目录: 1.开篇介绍 2.NET并行计算基本介绍 3.并行循环使用模式 3.1并行For循环 3.2并行ForEach循环 3.3并行LINQ(PLI ...
- Maven中有三大模块
Maven中有三大模块 在Maven中有三大模块,分别是依赖.仓库.生命周期和插件,我们接下来下来介绍下依赖,为了方便起见我们还是以案例来说: 1.首先建立一个maven项目,这里我建立一个user的 ...
- 迷你MVVM框架 avalonjs 0.95发布
迷你MVVM框架 avalonjs 0.95发布 本版本最主要的改进是ms-with 深层绑定的实现,至少,avalon1.0所有重要的feature已经开发完毕,之后就是小补小漏,性能优化了. ms ...
- Asp.net+jquery+ajaxpro异步仿Facebook纵向时间轴效果
Asp.net+jquery+ajaxpro异步仿Facebook纵向时间轴效果 在一个项目中,用到了时间轴展示产品的开发进度,为了更好用户体验,想到了Facebook的timeline效果, 搜了一 ...
- java正则表达式去除html标签
当我们用ckeditor或其他一些在线文本编辑器的时候 内容里会有很多的标签 如下片段: <p><img alt="" src="/img/upload ...
- 在多线程中进行UI操作--ios学习笔记
iOS 上不建议在非主线程进行UI操作,在非主线程进行UI操作有很大几率会导致程序崩溃,或者出现预期之外的效果. 我开始不知道这一点,在子线程中进行了弹窗操作,结果程序就出问题了! 报的错误是(EXC ...
- C#新功能--命名参数与可选参数
C#新功能--命名参数与可选参数 可能是篇幅太短了,又被打入冷宫了.先重发一篇加上可选参数.本来不想加这个呢,因为可选参数可能大家用的会多点.其实这 两个在VB中早就有了,在C#中,只有在.net4以 ...