题面

我 想 扇 死 自 己

void up(int x){if(x){size[x]=cnt[x];//我TM这行忘了if(son[x][0])size[x]+=size[son[x][0]];if(son[x][1])size[x]+=size[son[x][1]];}}

4个小时!调一道模板!我敲里码!

上道splay刚因为细节打错浪费了3个小时时间,这次就又**重现了

不多说了,先把splay抄上10遍,手写!

-----------以下是正经题解----------------

第一道树套树:线段树套splay

对于线段树的每一段区间建splay维护这段的信息

在合并时:

排名相加;

前驱取max;

后继取min;

比较麻烦的是查询数值,需要二分答案.

以数值为值域进行二分,不断询问mid的排名来缩小范围。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=4000005,inf=1e9;
int n,m,a[N];int root[N],son[N][3],fa[N],key[N],size[N],type,cnt[N];void clear(int x){if(!x)return ;fa[x]=cnt[x]=son[x][0]=son[x][1]=size[x]=key[x]=0;}int pre(int k){int now=son[root[k]][0];while(son[now][1])now=son[now][1];return now;}bool judge(int x){return son[fa[x]][1]==x;}void up(int x){if(x){size[x]=cnt[x];if(son[x][0])size[x]+=size[son[x][0]];if(son[x][1])size[x]+=size[son[x][1]];}}void rotate(int x){int old=fa[x],oldf=fa[old],lr=judge(x);son[old][lr]=son[x][lr^1];fa[son[old][lr]]=old;son[x][lr^1]=old;fa[old]=x;fa[x]=oldf;if(oldf)son[oldf][son[oldf][1]==old]=x;up(old);up(x);}void splay(int k,int x){for(int f;f=fa[x];rotate(x))if(fa[f])rotate(judge(x)==judge(f)?f:x);root[k]=x;}void ins(int k,int x){if(!root[k]){type++;key[type]=x;root[k]=type;cnt[type]=size[type]=1;fa[type]=son[type][0]=son[type][1]=0;return ;}int now=root[k],f=0;while(1){if(x==key[now]){cnt[now]++;up(now);up(f);splay(k,now);return ;}f=now;now=son[now][key[now]<x];if(!now){type++;size[type]=cnt[type]=1;son[type][0]=son[type][1]=0;son[f][x>key[f]]=type;fa[type]=f;key[type]=x;up(f);splay(k,type);return ;}}}int getrank(int k,int x){int now=root[k],ans=0;while(1){if(!now)return ans;if(x==key[now])return (son[now][0]?size[son[now][0]]:0)+ans;else if(x>key[now]){ans+=(son[now][0]?size[son[now][0]]:0)+cnt[now];now=son[now][1];}else if(x<key[now])now=son[now][0];}}int findpos(int k,int x){int now=root[k];while(1){if(x==key[now])return now;else if(x<key[now])now=son[now][0];else now=son[now][1];}}int findpre(int k,int x){int now=root[k],ans=0;while(now){if(key[now]<x){if(ans<key[now])ans=key[now];now=son[now][1];}else now=son[now][0];}return ans;}int findnxt(int k,int x){int now=root[k],ans=inf;while(now){if(key[now]>x){if(ans>key[now])ans=key[now];now=son[now][0];}else now=son[now][1];}return ans;}void del(int k,int x){int now=findpos(k,x);splay(k,now);if(cnt[root[k]]>1){cnt[root[k]]--;up(root[k]);return ;}else if(!son[root[k]][0]&&(!son[root[k]][1])){clear(root[k]);root[k]=0;return ;}int old=root[k];if(son[root[k]][0]*son[root[k]][1]==0){if(!son[root[k]][0])root[k]=son[root[k]][1];else root[k]=son[root[k]][0];fa[root[k]]=0;clear(old);return ;}int L=pre(k);splay(k,L);son[root[k]][1]=son[old][1];fa[son[old][1]]=root[k];clear(old);up(root[k]);}#define ls(k) k<<1#define rs(k) k<<1|1void update(int k,int l,int r,int pos,int val){ins(k,val);if(l==r)return ;int mid=l+r>>1;if(pos<=mid)update(ls(k),l,mid,pos,val);else update(rs(k),mid+1,r,pos,val);return ;}int rank(int k,int l,int r,int L,int R,int val){if(l>=L&&r<=R){int res=getrank(k,val);return res;}int mid=l+r>>1,res=0;if(L<=mid)res+=rank(ls(k),l,mid,L,R,val);if(R>mid)res+=rank(rs(k),mid+1,r,L,R,val);return res;}void modify(int k,int l,int r,int pos,int val){del(k,a[pos]);ins(k,val);if(l==r)return ;int mid=l+r>>1;if(pos<=mid)modify(ls(k),l,mid,pos,val);else modify(rs(k),mid+1,r,pos,val);}int getpre(int k,int l,int r,int L,int R,int val){if(l>=L&&r<=R)return findpre(k,val);int mid=l+r>>1,res=0;if(L<=mid)res=max(res,getpre(ls(k),l,mid,L,R,val));if(R>mid)res=max(res,getpre(rs(k),mid+1,r,L,R,val));return res;}int getnxt(int k,int l,int r,int L,int R,int val){if(l>=L&&r<=R)return findnxt(k,val);int mid=l+r>>1,res=inf;if(L<=mid)res=min(res,getnxt(ls(k),l,mid,L,R,val));if(R>mid)res=min(res,getnxt(rs(k),mid+1,r,L,R,val));return res;}
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;
}
int main()
{n=read();m=read();int op,maxx=0;for(int i=1;i<=n;i++){a[i]=read();update(1,1,n,i,a[i]);maxx=max(maxx,a[i]);}while(m--){op=read();if(op==1){int l=read(),r=read(),val=read();printf("%d\n",rank(1,1,n,l,r,val)+1);}else if(op==2){int l=read(),r=read(),val=read();int L=0,R=maxx+1;while(L!=R){int mid=L+R>>1;int res=rank(1,1,n,l,r,mid);//cout<<"***"<<res<<endl;if(res<val)L=mid+1;else R=mid;}printf("%d\n",L-1);}else if(op==3){int pos=read(),val=read();modify(1,1,n,pos,val);a[pos]=val;maxx=max(maxx,val);}else if(op==4){int l=read(),r=read(),val=read();printf("%d\n",getpre(1,1,n,l,r,val));}else if(op==5){int l=read(),r=read(),val=read();printf("%d\n",getnxt(1,1,n,l,r,val));}}return 0;
}

转载于:https://www.cnblogs.com/Rorschach-XR/p/11019342.html

二逼平衡树 题解(树套树)相关推荐

  1. 【BZOJ3196】【Tyvj1730】二逼平衡树,第一次的树套树(线段树+splay)

    传送门1 传送门2 写在前面:创造迄今最长的正常代码的记录 思路:个人感觉这个树套树就是对线段树的每个区间建一棵splay来维护,最初觉得这个方法会爆T爆M--(实际上真的可能会爆).对于5个操作,我 ...

  2. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2271  Solved: 935 [Submit][St ...

  3. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

    [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...

  4. [luogu3380][bzoj3196]【模板】二逼平衡树【树套树】

    题目地址 [洛谷传送门] 题目大意 区间查询k的排名,查找k排名的数,单点修改,区间前驱,区间后继. 感想 真的第一次写树套树,整个人都不对了.重构代码2次,发现样例都过不了,splay直接爆炸,可能 ...

  5. P3380 【模板】二逼平衡树(树套树)

    传送门 查询 kkk 在区间内的排名 查询区间内排名为 kkk的值 修改某一位值上的数值 查询 kkk 在区间内的前驱(前驱定义为严格小于 xxx,且最大的数,若不存在输出 −2147483647-2 ...

  6. 树套树-线段树套平衡树

    作用 线段树的作用是区间修改和查询,平衡树的作用是查询第k大,k的排名,前驱,后继.这两个结合起来,就变成了可以区间修改和查询第k大,k的排名,前驱,后继的数据结构:树套树-线段树套平衡树. 实现 先 ...

  7. Bzoj 3196 Tyvj 1730 二逼平衡树

    3196: Tyvj 1730 二逼平衡树 >原题链接< Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  8. Uva 3767 Dynamic len(set(a[L:R])) 树套树

    Dynamic len(set(a[L:R])) Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/in ...

  9. 【Luogu】P3380树套树模板(线段树套Splay)

    题目链接 幸甚至哉,歌以咏志. 拿下了曾经是那么遥不可及的线段树,学会了曾经高不可攀的平衡树,弄懂了装B的时候才挂在嘴边的树套树. 每道模板都是链上的一颗珠子.把它们挨个串起来,就成为我成长的历程. ...

最新文章

  1. API HTTP 请求调试:Postman
  2. jQuery插件开发--(转)
  3. 前馈pid系数_SPMSM控制——基于模型的电流前馈控制及思考
  4. git : 上传大文件或者PDF或者二进制文件导致无法上传
  5. 扩展单元格 == 报表
  6. html5 input file样式修改,css为input type=file设置自定义样式
  7. 在线分数加减乘除计算器
  8. HDU2546 饭卡【贪心+0-1背包】
  9. JIRA 饼图中文乱码
  10. 云运维管家服务器,云平台随身管理-我的“运维管家”
  11. 深度跳转-scheme
  12. arp -s命令报错,ARP项添加失败:请求的操作需要提升。
  13. 任务栏-IDEA图标变白色
  14. 如何把照片压缩到20k一下_如何将照片压缩到20k_手机怎么把照片压缩到20k
  15. 把这本书讲给更多人(中):两次历史上著名的谋杀案?
  16. Centos 7 安装 jq json 插件以及使用方法
  17. 彻底解决SPI协议OLED屏幕通道干扰乱码
  18. 关于emacs字体放大问题
  19. 杨振宁追求的物理美学,居然在这里实现,物理学史上颜值最高的组合,看完后跪了……
  20. NLP 自然语言初体验

热门文章

  1. ansible常用模块入门
  2. 星云链智能合约开发(六):智能合约开发与部署
  3. Java Swing中键盘事件的处理
  4. 查看linux服务器内存使用情况,不够时创建Swap、手动 cached
  5. 阿里巴巴1582.73亿背后的持续交付如何玩
  6. C#DataTable2Json(附时间格式化)
  7. 中国首个 SaaS 模式的云告警平台 iOS 版 APP 上线
  8. hdu 1250 大数相加并用数组储存
  9. 酷盘API C# 测试版
  10. [windows网络编程]tcp/udp编程初步详解-转