Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数
题解
树套树,调了好久,至今都不是很清楚为什么删除节点的时候不能直接减一而必须先....说不清楚了,在代码里体现吧
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<iostream>
  4 using namespace std;
  5 const int inf=100000000,N=3000001,M=200001;
  6 int num[N],rnd[N],size[N],ls[N],rs[N],root[M],w[N],a[M];
  7 int sz,n,m,opt,l,r;
  8 void updata(int k){size[k]=size[ls[k]]+size[rs[k]]+w[k];}
  9 void rturn(int &k){int t=ls[k];ls[k]=rs[t];rs[t]=k;size[t]=size[k];updata(k);k=t;}
 10 void lturn(int &k){int t=rs[k];rs[k]=ls[t];ls[t]=k;size[t]=size[k];updata(k);k=t;}
 11 void insert(int &k,int x){
 12     if (!k){
 13         k=++sz;num[k]=x;rnd[k]=rand();size[k]=w[k]=1;return;
 14     }
 15     size[k]++;
 16     if (x==num[k]) {w[k]++;return;}
 17     if (x<num[k]) {insert(ls[k],x);if (rnd[ls[k]]<rnd[k]) rturn(k);}
 18     if (x>num[k]) {insert(rs[k],x);if (rnd[rs[k]]<rnd[k]) lturn(k);}
 19 }
 20
 21 void del(int &k,int x){
 22     if (!k) return;
 23     if (num[k]==x){
 24         if (w[k]>1){w[k]--;size[k]--;return;}//就是这里,不知道为什么不是在前面直接size[k]--
 25         if(ls[k]*rs[k]==0){k=ls[k]+rs[k]; return;}
 26         if (rnd[ls[k]]<rnd[rs[k]])rturn(k),del(k,x);
 27         else lturn(k),del(k,x);
 28     }
 29     else if (num[k]>x) del(ls[k],x),size[k]--;else del(rs[k],x),size[k]--;
 30 }
 31
 32 void change(int pos,int x){
 33     int k=1,l=1,r=n,mid=(l+r)>>1;
 34     while (l!=r){
 35         mid=(l+r)>>1;
 36         del(root[k],a[pos]);
 37         insert(root[k],x);
 38         if (mid>=pos)k=k<<1,r=mid;
 39         else k=k<<1|1,l=mid+1;
 40     }
 41     mid=(l+r)>>1;
 42     del(root[k],a[pos]);
 43     insert(root[k],x);
 44 }
 45
 46 int solve_rank(int k,int x){
 47     if (!k) return 0;
 48     int l=ls[k],r=rs[k];
 49     if (num[k]==x) return size[l];
 50     else if (num[k]>x) return solve_rank(l,x);
 51     else return solve_rank(r,x)+size[l]+w[k];
 52 }
 53
 54 int get_rank(int k,int l,int r,int L,int R,int x){
 55     if (l==L&&r==R) return (solve_rank(root[k],x));
 56     int mid=(l+r)>>1;
 57     if (R<=mid) return get_rank(k<<1,l,mid,L,R,x);
 58     else if (L>mid) return get_rank(k<<1|1,mid+1,r,L,R,x);
 59     else return get_rank(k<<1,l,mid,L,mid,x)+get_rank(k<<1|1,mid+1,r,mid+1,R,x);
 60 }
 61
 62 void build(int x,int y){
 63     int l=1,r=n,k=1,mid=(l+r)>>1;
 64     while(l!=r){
 65         insert(root[k],y);
 66         if (mid>=x) r=mid,mid=(l+r)>>1,k=k<<1;
 67         else l=mid+1,mid=(l+r)>>1,k=k<<1|1;
 68     }
 69     insert(root[k],y);
 70 }
 71
 72 int get_num(int x,int y,int z){
 73     int l=1,r=inf,ans;
 74     while (l<=r){
 75         int mid=(l+r)>>1;
 76         int tmp=get_rank(1,1,n,x,y,mid);
 77         if (tmp<=z) ans=mid,l=mid+1;//因为有重复的数字,tmp偏小
 78         else r=mid-1;
 79     }
 80     return ans;
 81 }
 82
 83 int solve_pre(int k,int x){
 84     int l=ls[k],r=rs[k];
 85     if (!k) return 0;
 86     if (num[k]<x) return max(num[k],solve_pre(r,x));//这里不要顺手打上=
 87     else return solve_pre(l,x);
 88 }
 89
 90 int get_pre(int k,int l,int r,int L,int R,int x){
 91     if (l==L&&r==R) return (solve_pre(root[k],x));
 92     int mid=(l+r)>>1;
 93     if (R<=mid) return get_pre(k<<1,l,mid,L,R,x);
 94     else if (L>mid) return get_pre(k<<1|1,mid+1,r,L,R,x);
 95     else return max(get_pre(k<<1,l,mid,L,mid,x),get_pre(k<<1|1,mid+1,r,mid+1,R,x));
 96 }
 97
 98 int solve_after(int k,int x){
 99     int l=ls[k],r=rs[k];
100     if (!k) return inf;
101     if (num[k]>x) return min(num[k],solve_after(l,x));//这里不要顺手打上=*2
102     else return solve_after(r,x);
103 }
104
105 int get_after(int k,int l,int r,int L,int R,int x){
106     if (l==L&&r==R) return (solve_after(root[k],x));
107     int mid=(l+r)>>1;
108     if (R<=mid) return get_after(k<<1,l,mid,L,R,x);
109     else if (L>mid) return get_after(k<<1|1,mid+1,r,L,R,x);
110     else return min(get_after(k<<1|1,mid+1,r,mid+1,R,x),get_after(k<<1,l,mid,L,mid,x));
111 }
112
113 int main(){
114     freopen("sj.txt","r",stdin);
115     freopen("me.txt","w",stdout);
116     int k;
117     scanf("%d%d",&n,&m);
118     for (int i=1;i<=n;i++){scanf("%d",&a[i]);build(i,a[i]);}
119     for (int i=1;i<=m;i++){
120         scanf("%d%d%d",&opt,&l,&r);
121         if (opt!=3)scanf("%d",&k);
122         switch(opt){
123             case 1:printf("%d\n",get_rank(1,1,n,l,r,k)+1);break;
124             case 2:printf("%d\n",get_num(l,r,k-1));break;
125             case 3:change(l,r);a[l]=r;break;
126             case 4:printf("%d\n",get_pre(1,1,n,l,r,k));break;
127             case 5:printf("%d\n",get_after(1,1,n,l,r,k));break;
128         }
129     }
130 }

转载于:https://www.cnblogs.com/wuminyan/p/5152475.html

【BZOJ3196】Tyvj 1730 二逼平衡树相关推荐

  1. Bzoj 3196 Tyvj 1730 二逼平衡树

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

  2. bzoj 3196/tyvj p1730 二逼平衡树

    原题链接:http://www.tyvj.cn/p/1730 树套树... 如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #incl ...

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

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

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

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

  5. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

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

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

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

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

  8. 二逼平衡树——树套树(线段树套Splay平衡树)

    题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...

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

    恭喜你 以分块的姿势通过了此题 #include<cmath> #include<cstdio> #include<algorithm> #define inf ( ...

最新文章

  1. MYSQL体系结构-来自期刊
  2. 一些常用工具地址,随时更新中~
  3. tabcontainer控件太长_AjaxControlToolKit--TabContainer控件的介绍收藏[摘录]
  4. 可持久化普通线段树 ---- P2839 [国家集训队]middle 可持久化普通线段树 + 二分 求中位数最大值
  5. MapReduce 论文翻译
  6. Checkpoint IC_WEBCLIENT_PROCESS_CNTRL_DBG
  7. 静态创意和动态创意_我在22岁时学到的关于创意指导的知识
  8. 配置mysql为主主复制步骤
  9. linux set权限,Linux 特殊权限set_uid(示例代码)
  10. 微信第三方扫描登录 java源代码_微信开放平台基于网站应用授权登录源码(java)...
  11. 计算机视觉论文-2021-07-08
  12. 一些比较恶心的代码片段
  13. java post 403_求助啊。。。。。。给服务器POST JSON报403
  14. Jmeter发送get请求
  15. php libev扩展使用
  16. 基于WFST的语音识别解码器
  17. IT运维服务体系建设思路
  18. 计算机专业的文献综述题目,计算机专业文献综述格式及要求
  19. 新构造运动名词解释_新构造运动
  20. [转]ubuntu常用软件

热门文章

  1. C#学习笔记(C#与C++的差异)001
  2. 谁来谈谈Google Earth的核心技术和架构?(转)
  3. 数据统计分析中的几点
  4. linux命令(51):set 指定行,直接替换并修改文件
  5. 程序员的魔法——用Masking GAN让100,000人都露出灿烂笑容
  6. 【POI xls】解析xls遇到的问题
  7. CISSP考前总复习
  8. c语言外部中断th0,帮忙看看void int0() interrupt 1 //采用中断0 控制节拍 { TH0=0xd8; TL0=0xef; n--; } 啥意思...
  9. Struts2-表单验证的两种方式
  10. 漫谈递归:从斐波那契开始了解尾递归