博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Contest20180313]灵大会议
阅读量:5905 次
发布时间:2019-06-19

本文共 2284 字,大约阅读时间需要 7 分钟。

为了方便才用lct,没想到最后要加读入优化才能过...

有一个结论就是在一条链上,如果能找到一个点使得这个点划分链左右两边的树节点权值和最相近,那么这个点就是答案

用lct维护,每个splay节点存树节点权值$v_x$,树边权值$w_x$,splay中最左节点权值$lv_x$,最右节点权值$rv_x$,树节点权值和$sv_x$,树边权值和$sw_x$,这棵子树向左贡献的答案$pl_x$,这棵子树向右贡献的答案$pr_x$

对于每个询问,先把对应的链提取出来,然后在这棵splay上二分找到分两边点权和最平均的点(二分过程用$sv$和$lv$判断),找到点之后就可以直接输出答案了

修改直接修改

#include
#define NUM(x) (48<=x&&x<=57)char c[21000000]={0};int ns=0;inline int rd(){ while(!NUM(c[ns]))ns++; int q=0; while(NUM(c[ns]))q=(q<<3)+(q<<1)+c[ns++]-48; return q;}#define ll long longint fa[320010],ch[320010][2],r[320010];ll v[320010],lv[320010],rv[320010],w[320010],sv[320010],sw[320010],pl[320010],pr[320010];#define ls ch[x][0]#define rs ch[x][1]void pushup(int x){ lv[x]=ls?lv[ls]:v[x]; rv[x]=rs?rv[rs]:v[x]; sv[x]=sv[ls]+sv[rs]+v[x]; sw[x]=sw[ls]+sw[rs]+w[x]; pl[x]=pl[ls]+pl[rs]+v[x]*sw[ls]+(sw[ls]+w[x])*sv[rs]; pr[x]=pr[ls]+pr[rs]+v[x]*sw[rs]+(sw[rs]+w[x])*sv[ls];}templatevoid swap(C&a,C&b){ C c=a; a=b; b=c;}void rev(int x){ r[x]^=1; swap(lv[x],rv[x]); swap(pl[x],pr[x]); swap(ls,rs);}void pushdown(int x){ if(r[x]){ if(ls)rev(ls); if(rs)rev(rs); r[x]=0; }}void rot(int x){ int y,z,f,b; y=fa[x]; z=fa[y]; f=ch[y][0]==x; b=ch[x][f]; fa[x]=z; fa[y]=x; if(b)fa[b]=y; ch[x][f]=y; ch[y][f^1]=b; if(ch[z][0]==y)ch[z][0]=x; if(ch[z][1]==y)ch[z][1]=x; pushup(y); pushup(x);}bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}void gao(int x){ if(!isrt(x))gao(fa[x]); pushdown(x);}void splay(int x){ int y,z; gao(x); while(!isrt(x)){ y=fa[x]; z=fa[y]; if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x); rot(x); }}void access(int x){ int y=0; while(x){ splay(x); rs=y; pushup(x); y=x; x=fa[x]; }}void makert(int x){ access(x); splay(x); rev(x);}void link(int x,int y){ makert(x); fa[x]=y;}int find(int x,ll d){ pushdown(x); if(sv[ls]+v[x]>d)return find(ls,d); d-=sv[ls]+v[x]; if(rs&&lv[rs]<=d)return find(rs,d); return x;}ll query(int x,int y){ makert(x); access(y); splay(x); if(lv[x]<=sv[x]>>1){ x=find(x,sv[x]>>1); splay(x); x=rs; } pushdown(x); while(ls){ x=ls; pushdown(x); } splay(x); return pr[ls]+pl[rs];}int main(){ int len=fread(c,1,21000000,stdin); c[len]=0; int n,q,i,x,y; n=rd(); for(i=1;i<=n;i++){ v[i]=rd(); pushup(i); } for(i=1;i

转载于:https://www.cnblogs.com/jefflyy/p/8556888.html

你可能感兴趣的文章
基本类型的类型转换(隐式类型转换)和强制类型转换(译一)
查看>>
【python socket编程】—— 3.响应
查看>>
2017我的个人总结:得与失
查看>>
javascript---Symbol类型, 引用类型, 作用域
查看>>
Mongodb使用
查看>>
【Node.js 微信公众号实战】2.Node.js access_token的获取、存储及更新
查看>>
PWA之Workbox缓存策略分析
查看>>
js仿苹果悬浮可拖拽按钮,并且点击展开效果
查看>>
PHPRAP v1.0.4版本发布了,支持在线调试接口
查看>>
ELSE 技术周刊(2017.10.30期)
查看>>
EasySignSeekBar一个漂亮而强大的自定义view
查看>>
《Node.js设计模式》基于ES2015+的回调控制流
查看>>
分析Nginx 源码 - ngx_palloc文件总结
查看>>
JetBrains C/C++ IDE CLion 安装
查看>>
一个vue的可拖拽的瀑布流布局组件
查看>>
基于SpringCloud的微服务架构实战案例项目
查看>>
ng2-stomp-service ng2 ng4 websocket使用
查看>>
leetcode 438. Find All Anagrams in a String
查看>>
HTML5 拖放(Drag 和 Drop)详解与实例
查看>>
分布式任务调度平台的自动化部署
查看>>