地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196

题目:

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4320  Solved: 1662
[Submit][Status][Discuss]

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可能为负数
 
思路:
  第一次写树套树,以前一直觉得树套树是很可怕的东西,写了后发现思想很简单
  就是。。。。代码好长!debug麻烦!
  写了两小时,debug三小时。。
  不过1A了,美滋滋!
  代码跑了快九秒,好气哦,一定是姿势不对
 /**************************************************************
Problem: 3196
User: weeping
Language: C++
Result: Accepted
Time:8668 ms
Memory:83520 kb
****************************************************************/ #include <bits/stdc++.h> using namespace std; #define lc ch[x][0]
#define rc ch[x][1]
#define pr fa[x] inline int read()
{
int a=,f=; char c=getchar();
while (c<''||c>'') {if (c=='-') f=-; c=getchar();}
while (c>=''&&c<='') {a=a*+c-''; c=getchar();}
return a*f;
} const int N = 5e4+;
const int M = 3e6; int n, m, ans, val[N];
int tot, rt[M], ch[M][], fa[M], key[M], sz[M], cnt[M]; inline int wh(int x) { return ch[pr][] == x;} inline void init(int x,int ls,int ky)
{
lc=rc=,sz[x]=cnt[x]=,key[x]=ky,pr=ls;
}
inline void push_up(int x)
{
sz[x]=sz[lc]+sz[rc]+cnt[x];
}
void rotate(int x)
{
int f = fa[x], gf = fa[f], t1 = wh(x);
if( gf ) ch[gf][wh(f)] = x;
fa[x] = gf, ch[f][t1] = ch[x][^t1], fa[ch[f][t1]] = f;
ch[x][t1^] = f, fa[f] = x;
push_up( f ), push_up( x );
}
void splay(int o,int x,int tar)
{
for(;pr!=tar;rotate(x))
if(fa[pr]!=tar) rotate(wh(x)==wh(pr)?pr:x);
if(!tar) rt[o]=x;
}
//void debug(int x)
//{
// if(!x) return;
// if(lc) debug(lc);
// for(int i=1;i<=cnt[x];i++)
// printf("%d ",key[x]);
// if(rc) debug(rc);
//}
void insert(int o,int ky)
{
int x=rt[o],ls=rt[o];
while(x)
{
if(key[x]==ky)
{
sz[x]++,cnt[x]++,splay(o,x,);return;
}
ls=x,x=ch[x][ky>key[x]];
}
init(++tot,ls,ky);
if(!rt[o]) { rt[o]=tot; return ;}
x=ls, ch[x][ky>key[x]]=tot;
splay(o,tot,);
}
int find(int o,int ky)
{
int x=rt[o];
//debug(rt[o]);printf("\n");
while(x)
{
if(key[x]==ky) break;
x=ch[x][ky>key[x]];
}
if(x) splay(o,x,);
else x=-;
return x;
}
void merge(int o,int x,int y)
{
if(!x){rt[o]=y;return;}
if(!y) {rt[o]=x;return;}
while(rc) x=rc;
splay(o,x,);
rc=y,fa[y]=x;
push_up(x);
}
void del(int o,int ky)
{
if(!rt[o]) return;
int x=find(o,ky);
if(cnt[x]>) {cnt[x]--,sz[x]--;return;}
int tl=lc,tr=rc;
fa[tl]=fa[tr]=cnt[x]=sz[x]=lc=rc=;
if(sz[x]==) {rt[o]=;return;}
merge(o,tl,tr);
}
void getpre(int x,int ky)
{
if(!x)return;
if(key[x]<ky) ans=max(ans,key[x]),getpre(rc,ky);
else getpre(lc,ky);
}
void getnext(int x,int ky)
{
if(!x) return;
if(key[x]>ky) ans=min(ans,key[x]),getnext(lc,ky);
else getnext(rc,ky);
}
int getsz(int o,int ky)
{
int x=rt[o],ret=;
while(x)
{
if(key[x]==ky) return ret+sz[lc];
if(key[x]<ky) ret+=sz[lc]+cnt[x],x=rc;
else x=lc;
}
return ret;
} void update(int o,int l,int r,int pos,int x,int op=)
{
if(op) del(o,val[pos]);
insert(o,x);
//debug(rt[o]);printf("\n");
if(l==r) return ;
int mid=l+r>>;
if(pos<=mid) update(o<<,l,mid,pos,x,op);
else update(o<<|,mid+,r,pos,x,op);
}
int get_rank(int o,int l,int r,int nl,int nr,int ky)
{
//debug(rt[o]);printf("\n");
if(nl==l&&r==nr) return getsz(o,ky);
int mid=l+r>>;
if(nr<=mid) return get_rank(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_rank(o<<|,mid+,r,nl,nr,ky);
return get_rank(o<<,l,mid,nl,mid,ky)+get_rank(o<<|,mid+,r,mid+,nr,ky);
}
void get_pre(int o,int l,int r,int nl,int nr,int ky)
{
if(nl==l&&r==nr) return getpre(rt[o],ky);
int mid=l+r>>;
if(nr<=mid) return get_pre(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_pre(o<<|,mid+,r,nl,nr,ky);
get_pre(o<<,l,mid,nl,mid,ky),get_pre(o<<|,mid+,r,mid+,nr,ky);
}
void get_next(int o,int l,int r,int nl,int nr,int ky)
{
//debug(rt[o]);printf("\n");
if(nl==l&&r==nr) return getnext(rt[o],ky);
int mid=l+r>>;
if(nr<=mid) return get_next(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_next(o<<|,mid+,r,nl,nr,ky);
get_next(o<<,l,mid,nl,mid,ky),get_next(o<<|,mid+,r,mid+,nr,ky);
}
int get_kth(int nl,int nr,int k)
{
int l=,r=1e8+,ans=;
while(l<=r)
{
int mid=l+r>>;
if(get_rank(,,n,nl,nr,mid)+<=k) l=mid+,ans=mid;
else r=mid-;
}
return ans;
}
int main(void)
{
n=read(),m=read();
for(int i=;i<=n;i++)
val[i]=read(),update(,,n,i,val[i]);
int op,l,r,x;
while(m--)
{
op=read(),l=read(),r=read();
if(op==)
{update(,,n,l,r,);val[l]=r;continue;}
x=read();
if(op==)
ans=get_rank(,,n,l,r,x)+;
else if(op==)
ans=get_kth(l,r,x);
else if(op==)
ans=-0x3f3f3f3f,get_pre(,,n,l,r,x);
else
ans=0x3f3f3f3f,get_next(,,n,l,r,x);
printf("%d\n",ans);
}
}

bzoj3196: Tyvj 1730 二逼平衡树 树套树的更多相关文章

  1. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  2. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  3. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  4. 【分块】bzoj3196 Tyvj 1730 二逼平衡树

    分块 或 树套树. 在每个块中维护一个有序表,查询时各种二分,全都是分块的经典操作,就不详细说了. 块的大小定为sqrt(n*log2(n))比较快. #include<cstdio> # ...

  5. 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

    线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...

  6. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  7. BZOJ3196: Tyvj 1730 二逼平衡树

    传送门 主席树的常数蜜汁优越,在BZOJ上跑了rnk1. 做法很简单,主席树套BIT. 1-3做法很简单,第四个和第五个做法转换成前两个就行了. //BZOJ 3196 //by Cydiater / ...

  8. [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

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

  9. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

随机推荐

  1. vmware12如何安装macOSX虚拟机

    vmware默认是不支持创建OSX系统的虚拟机的,但是安装一个名为unlocker208的破解补丁之后就可以安装了. 下载的地址和使用的方法参考这个地址:http://www.jb51.net/sof ...

  2. 一个lucene源码分析的博客

    ITpub上的一个lucene源码分析的博客,写的比较全面:http://blog.itpub.net/28624388/cid-93356-list-1/

  3. WIN7开启wifi热点

    1.首先,先确定自己的笔记本网卡支持“启动承载网络”的功能,使用管理员运行cmd命令.启用管理员运行CMD的方法Windows-所有程序-附件-运行(右键,以管理员身份运行)在弹出的CMD窗口里面敲击 ...

  4. linux下jmeter持续集成Jenkins部署时问题解决

    之前成linux下安装了Jenkins,并做了一些简单的工作,这次正好将jmeter也集成进去,在实际操作时发现好多坑,写下做记录 怎么安装这里就不介绍了,网上很多资料,这里只记录问题,以供大家参数 ...

  5. Unity3D笔记 NUGUI 一

    NGUI是严格遵循KISS原则(KISS原则,keep it simple and stupid ,简单的理解这句话就是,要把一个系统做的连白痴都会用.这就是用户体验的高层境界了,好听的说法也是有的, ...

  6. Sql Server 统计当天数据

    方法一. ),日期字段名,)),) 方法二. Access: * FROM 表名 WHERE DAY(日期字段名)=DAY(NOW()) 查询当天之前一天的数据

  7. httpclient 请求 json 数据

    基于\httpcomponents-client-4.5.5需要引入相关jar包如下: 必须导入commons-logging-1.2.jar,否则会提示 json api接口地址: https:// ...

  8. sublime text 3 常见问题总结 pyv8

    安装 这个过程下一步下一步就行 激活 在help菜单中选择输入验证码,如下整个都是: ----- BEGIN LICENSE ----- Andrew Weber Single User Licens ...

  9. Bazel构建工具的安装

    官方Doc:https://docs.bazel.build/versions/master/install-ubuntu.html 使用Bazel定制的APT存储库 (recommended) 1. ...

  10. 解决oracle12c安装报“[INS-30131]执行安装程序验证所需的初始设置失败(原因:无法访问临时位置)”方法

    安装过很多次oracle,顺顺利利的,今天在新机子上安装oracle12c client过程中竟然神奇的报出一个错误: 很明显的,已经很明确的给出了安装失败的原因:无法访问临时位置!实际上,在安装数据 ...