要找的就是这棵树的带权重心,以带权重心为根时每棵子树的权值和不超过总权值和的一半。

因此按$\frac{v[i]}{\sum v[i]}$的概率随机选取一个点$x$,则重心有$\frac{1}{2}$的概率落在$1$到$x$的路径上,期望随机次数为$O(1)$。

随机方式可以直接随机一个$1$到$\sum v[i]$之间的数,然后相当于找第$k$小值,线段树上二分可以做到$O(\log n)$定位。

设$sum[x]$表示$x$子树的权值和,可以用LCT打标记维护。

在表示$1$到$x$路径的Splay上找到最靠右的点$y$,满足$2sum[y]>sum[1]$;若$y$最重的儿子$z$不满足$2sum[z]>sum[1]$,则$y$是答案。

需要快速查询一个点的儿子里的$sum$的最大值,因此用set维护每个点的虚儿子即可。

一共$O(n\log n)$次虚实边切换,时间复杂度$O(n\log^2n)$。

#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
typedef unsigned int U;
typedef long long ll;
typedef unsigned long long ull;
const int N=150010,M=524300;
int n,m,lim,i,op,x,y,ans,e[300010][3],val[N],pos[N],pre;ll sum[M];
int f[N],son[N][2],tmp[N];ll sz[N],vl[N],mx[N],tag[N];
multiset<ll>T[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline void tag1(int x,ll p){if(!x)return;tag[x]+=p;sz[x]+=p;mx[x]+=p;vl[x]+=p;
}
inline void pb(int x){if(tag[x])tag1(son[x][0],tag[x]),tag1(son[x][1],tag[x]),tag[x]=0;}
inline void umax(ll&a,ll b){a<b?(a=b):0;}
inline void up(int x){if(!x)return;mx[x]=vl[x]=sz[x];if(son[x][0]){umax(mx[x],mx[son[x][0]]);vl[x]=vl[son[x][0]];}if(son[x][1])umax(mx[x],mx[son[x][1]]);
}
inline void rotate(int x){int y=f[x],w=son[y][1]==x;son[y][w]=son[x][w^1];if(son[x][w^1])f[son[x][w^1]]=y;if(f[y]){int z=f[y];if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;}f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
inline void splay(int x){int s=1,i=x,y;tmp[1]=i;while(!isroot(i))tmp[++s]=i=f[i];while(s)pb(tmp[s--]);while(!isroot(x)){y=f[x];if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}rotate(x);}up(x);
}
inline void access(int x){for(int y=0;x;y=x,x=f[x]){splay(x);if(son[x][1])T[x].insert(vl[son[x][1]]);if(son[x][1]=y)T[x].erase(T[x].find(vl[y]));up(x);}
}
inline void add(int x,int p){access(x);splay(x);tag1(x,p);}
void build(int x,int a,int b){if(a==b){sum[x]=val[a];pos[a]=x;return;}int mid=(a+b)>>1;build(x<<1,a,mid);build(x<<1|1,mid+1,b);sum[x]=sum[x<<1]+sum[x<<1|1];
}
U SX=335634763,SY=873658265,SZ=192849106,SW=746126501;
inline ull xorshift128(){U t=SX^(SX<<11);SX=SY;SY=SZ;SZ=SW;return SW=SW^(SW>>19)^t^(t>>8);
}
inline ull myrand(){return (xorshift128()<<32)^xorshift128();}
inline int getrand(){ll k=myrand()%sum[1]+1;int x=1,a=1,b=lim,mid;while(a<b){mid=(a+b)>>1;ll tmp=sum[x<<1];if(k<=tmp){b=mid;x<<=1;}else{k-=tmp;a=mid+1;x=x<<1|1;}}return a;
}
inline void modify(int x,int y){val[x]=y;x=pos[x];sum[x]=y;for(x>>=1;x;x>>=1)sum[x]=sum[x<<1]+sum[x<<1|1];
}
inline int centroid(){for(int i=0;;i++){int x=getrand();if(!i&&ans)x=ans;access(x);splay(x);int y=x,ret=1;while(x){if(sz[x]*2>sum[1])ret=x;pb(x);if(mx[son[x][1]]*2>sum[1])x=son[x][1];else x=ret==x?0:son[x][0];if(x)y=x;}splay(y);access(ret);if(T[ret].size()==0||*T[ret].rbegin()*2<=sum[1])return ret;}
}
int main(){read(m),read(val[1]);n=lim=1;sz[1]=mx[1]=vl[1]=val[1];for(i=1;i<=m;i++){read(op);e[i][0]=op;if(op<3)read(e[i][1]),read(e[i][2]);if(op==1)lim++;}build(1,1,lim);for(i=1;i<=m;i++){op=e[i][0];x=e[i][1]^ans;y=e[i][2]^ans;if(op==1){modify(++n,y);f[n]=x;T[x].insert(0);add(n,y);}else if(op==2){add(x,y-val[x]);modify(x,y);}else{if(pre!=3){int now=centroid();ans=now;}printf("%d\n",ans);}pre=op;}return 0;
}

  

转载于:https://www.cnblogs.com/clrs97/p/10850999.html

BZOJ5243 : [Lydsy2017省队十连测]绝版题相关推荐

  1. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 93  Solved: 53 [Submit][Status ...

  2. BZOJ5217: [Lydsy2017省队十连测]航海舰队

    被FFT的空间卡了半天 后来发现根本不用开那么大- 首先可以把包含舰艇的那个小矩形找出来 将它一行一行连接成一个串T 其中舰艇位置为1其他位置为0 将大矩形也连成串S 其中礁石为1其他为0 两个串匹配 ...

  3. [Lydsy2017省队十连测]航海舰队

    SOL: 我们用FFT匹配字符串. 不知道为什么我的NTT挂了,贴一个别人的FFT. #include<bits/stdc++.h> #define ll long long #defin ...

  4. BZOJ5217: [Lydsy2017省队十连测]航海舰队 FFT

    被FFT的空间卡了半天 后来发现根本不用开那么大... 首先可以把包含舰艇的那个小矩形找出来 将它一行一行连接成一个串T 其中舰艇位置为1其他位置为0 将大矩形也连成串S 其中礁石为1其他为0 两个串 ...

  5. 2017.10.24队内互测——压轴出场的互测终曲|(*_-)

    出题人: Sherlock, Frank, WWQ, MurasameKatana 终于到了我们组出题啦. 题面都是我自己写的2333 Problem 1 :令咒 题目来源:http://codevs ...

  6. winpcap基本原理及常见应用_碳十四测年的基本原理和常见应用谬误

    如果说地层学原理是18世纪地质学给19世纪考古学的重要礼物,那么放射性碳定年法就是20世纪考古学最重要的进步之一.这两种方法都对年代判定做出了重要的贡献,因为若是没有某种类型的年代测定,我们就不可能建 ...

  7. 【bzoj 十连测】[noip2016十连测第三场]Problem C: 序列(静态主席树)

    Problem C: [noip2016十连测第三场]序列 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 78  Solved: 32 [Submi ...

  8. 2017.9.16队内互测——老年组Day1

    2017.9.16队内互测--老年组Day1 出题人:feather,MeiCo,Summer,Black Problem 1: 对于100%的数据,n<=1000 截图比较奇怪-还请见谅 简单 ...

  9. JAVA 判断简单密码算法_十道简单算法题二【Java实现】

    前言 清明不小心就拖了两天没更了-- 这是十道算法题的第二篇了-上一篇回顾:十道简单算法题 最近在回顾以前使用C写过的数据结构和算法的东西,发现自己的算法和数据结构是真的薄弱,现在用Java改写一下, ...

最新文章

  1. Android studio 使用心得(六)---android studio 如何加载.so文件
  2. 使用存储过程及触发器案例
  3. 安卓 ce linux,手持移动数据终端的操作系统有哪些?Windows CE,Mobile和安卓各有什么优缺点?...
  4. android下拉会谈效果,Android实现下拉展示条目效果
  5. 深入理解javascript原型和闭包
  6. element 表单回显验证_关于vue el-form表单报错的问题
  7. 美国警察开特斯拉追疑犯,时速飙到193公里,然后发现没电了...
  8. Serverless在大规模数据处理的实践
  9. linux ftp用户指定多个目录,linux ftp服务器下用户限制目录的方法
  10. 数据:以太坊2.0合约余额新增1.28万ETH
  11. android listview 连续调用 getview问题分析及解决。
  12. 023-数据结构与算法系列
  13. AI考拉技术分享会--Node.js APM 软件调研报告
  14. VirtualBox中,Windows虚拟机与主机共享文件夹不能用之一例
  15. vue实现留言板的功能_vue初探-简易留言板
  16. GoLang获取硬盘序列号
  17. netbeans乱码问题
  18. C语言实现七夕表白爱心
  19. 华为HCIP-DATACOM(821)411-440
  20. QQ查询信息php,查询QQ信息

热门文章

  1. 【EF学习笔记07】----------加载关联表的数据 贪婪加载
  2. ICML2021 | ALIGN:大力出奇迹,谷歌用18亿的图像-文本对训练了一个这样的模型
  3. OpenCV 4.x 中请别再用HAAR级联检测器检测人脸!有更好更准的方法
  4. Fellow观点:AI框架下的医疗影像教学
  5. Java hibernate假外键_java – Hibernate:外键的列数错误
  6. java oop入门_Java OOP入门起源
  7. 【TensorFlow】TensorFlow函数精讲之tf.nn.softmax_cross_entropy_with_logits
  8. 机器学习 | 决策树的理论与实践
  9. 基于C4.5神经网络集成
  10. centos7.4 mysql启动,centos7下mysql服务启动失败_网站服务器运行维护,centos7,mysql