【BZOJ】3196: Tyvj 1730 二逼平衡树(区间第k小+树套树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3196

Treap+树状数组
1WA1A,好伤心,本来是可以直接1A的,这次开始我并没有看题解,就写出来了,但是没有处理多个节点相同的情况,添加了多值单节点后,我竟然过不了样例,一直在调bug,哪想到是我改的时候手一抖把update的更新写错了。T_T,美好的青春就这样浪费了。
题目比较水,和Dynamic Rankings差不多,多思考就能写出来了。
#include <cstdio>
#include <cstdlib>
using namespace std;
#define lowbit(x) (x&-x)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int oo=~0u>>1, N=50005;
int a[N], cnt; struct node {
node* ch[2];
int key, size, wei, cnt;
node() { ch[0]=ch[1]=NULL; key=size=cnt=0; wei=rand(); }
void pushup() { size=ch[0]->size+ch[1]->size+cnt; }
}*null;
struct Treap {
node* root;
Treap() { root=null; }
void rot(node* &rt, bool d) {
node* c=rt->ch[!d]; rt->ch[!d]=c->ch[d]; c->ch[d]=rt;
rt->pushup(); c->pushup();
if(root==rt) root=c;
rt=c;
}
node* newnode(const int &key) {
node* ret=new node;
ret->key=key; ret->size=ret->cnt=1;
ret->ch[0]=ret->ch[1]=null;
return ret;
}
void insert(const int &key, node* &rt) {
if(rt==null) { rt=newnode(key); return; }
if(key==rt->key) { rt->cnt++; rt->size++; return; }
bool d=key>rt->key;
insert(key, rt->ch[d]);
if(rt->wei>rt->ch[d]->wei) rot(rt, !d);
rt->pushup();
}
void remove(const int &key, node* &rt) {
if(rt==null) return;
int d=key>rt->key;
if(key==rt->key) {
if(rt->cnt>1) { rt->cnt--; rt->size--; return; }
d=rt->ch[0]->wei>rt->ch[1]->wei;
if(rt->ch[d]==null) {
delete rt;
rt=null;
return;
}
rot(rt, !d);
remove(key, rt->ch[!d]);
}
else remove(key, rt->ch[d]);
rt->pushup();
}
int rank(const int &key) {
int ret=0, s;
for(node* t=root; t!=null;) {
s=t->ch[0]->size+t->cnt;
if(key>t->key) ret+=s, t=t->ch[1];
else t=t->ch[0];
}
return ret;
}
int suc(const int &key) {
int ret=oo+1;
for(node* t=root; t!=null;)
if(key>t->key) ret=t->key, t=t->ch[1];
else t=t->ch[0];
return ret;
}
int pre(const int &key) {
int ret=oo;
for(node* t=root; t!=null;)
if(key<t->key) ret=t->key, t=t->ch[0];
else t=t->ch[1];
return ret;
}
}*line[N], *nod[N], *q[N]; void getrange(int l, int r) {
cnt=0;
int r1=r;
while(l<=r1) {
if(r1-lowbit(r1)+1>=l) {
q[cnt++]=line[r1];
r1-=lowbit(r1);
}
else {
q[cnt++]=nod[r1];
r1--;
}
}
} int getrank(const int &key) {
int ret=0;
for(int i=0; i<cnt; ++i)
ret+=q[i]->rank(key);
return ret;
} int getans(int l, int r, int k) {
getrange(l, r);
int left=oo+1, right=oo, s;
for(int i=0; i<cnt; ++i) {
node* t=q[i]->root;
while(t!=null) {
if(t->key<left) {
t=t->ch[1];
continue;
}
if(t->key>right) {
t=t->ch[0];
continue;
}
s=getrank(t->key);
if(s==k-1) return t->key;
if(s<k-1) {
left=t->key;
t=t->ch[1];
}
else {
right=t->key;
t=t->ch[0];
}
}
}
return left;
} int getsuc(int l, int r, const int &key) {
getrange(l, r);
int ret=oo+1, t;
for(int i=0; i<cnt; ++i) {
t=q[i]->suc(key);
ret=max(ret, t);
}
return ret;
} int getpre(int l, int r, const int &key) {
getrange(l, r);
int ret=oo, t;
for(int i=0; i<cnt; ++i) {
t=q[i]->pre(key);
ret=min(ret, t);
}
return ret;
} int main() {
null=new node; null->wei=oo; null->ch[0]=null->ch[1]=null;
int n, m;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
line[i]=new Treap;
nod[i]=new Treap;
for(int j=i-lowbit(i)+1; j<=i; ++j)
line[i]->insert(a[j], line[i]->root);
nod[i]->insert(a[i], nod[i]->root);
}
int c, l, r, k;
while(m--) {
scanf("%d", &c);
if(c==1) {
scanf("%d%d%d", &l, &r, &k);
getrange(l, r);
printf("%d\n", getrank(k)+1);
}
else if(c==2) {
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", getans(l, r, k));
}
else if(c==3) {
scanf("%d%d", &l, &k);
for(int i=l; i<=n; i+=lowbit(i)) {
line[i]->remove(a[l], line[i]->root);
line[i]->insert(k, line[i]->root);
}
a[l]=k;
nod[l]->root->key=k;
}
else if(c==4) {
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", getsuc(l, r, k));
}
else if(c==5) {
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", getpre(l, r, k));
}
}
return 0;
}
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
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
4
3
4
9
HINT
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
Source
【BZOJ】3196: Tyvj 1730 二逼平衡树(区间第k小+树套树)的更多相关文章
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
- BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )
这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- bzoj 3196: Tyvj 1730 二逼平衡树
#include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap
http://www.lydsy.com/JudgeOnline/problem.php?id=3196 http://hzwer.com/2734.html 线段树套treap,似乎splay也可以 ...
- BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay
传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...
- BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)
题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...
- bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】
四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- bzoj 3196/tyvj p1730 二逼平衡树
原题链接:http://www.tyvj.cn/p/1730 树套树... 如下: #include<cstdio> #include<cstdlib> #include< ...
随机推荐
- postgresql 锁的定位
今天碰到了一个问题,锁定穷根追底把postgresql的锁研究了一番. 数据库查看锁 可以通过表 pg_locks来查看有哪些锁.sql如下: select a.locktype,a.database ...
- javascript的事件监听与捕获和冒泡
在前端开发中,我们经常需要对某些事件进行监听.这样只要在指定的元素上触发了该事件,就会执行一个回调来进行相关的操作. 而js中事件监听方法总共有三种,分别如下所示: element.addEventL ...
- malloc/free vs new/delete
malloc/new是库函数. new/delete是运算符. 对于非内部数据类型的对象而言,光用malloc/free 无法满足动态对象的要求.对象在创建的同时要自动执行构造函数, 对象在消亡之前要 ...
- cas单点登录用户名为中文的解决办法
当用户名为中文时,登录后返回的用户名乱码.解决这个问题只需要在客户端的CAS Validation Filter中添加下配置就行了. <init-param> <param-name ...
- 利用 Avisynth 2.5.8 的 ColorKeyMask 功能实现视频抠像
下载安装Avisynth 2.5.8 + 下载安装 FFMpeg 编写 Avisynth 脚本 mating.avs ----------------------------------------- ...
- UVALive 7270 Osu! Master (阅读理解题)
题目:传送门. 题意:阅读理解题,是一个osu的游戏,问得分.把题目翻译过来就是如果出现S或者BC后面跟的是1,ans就加1. #include <iostream> #include & ...
- 20145221 《Java程序设计》实验报告二:Java面向对象程序设计
20145221 <Java程序设计>实验报告二:Java面向对象程序设计 实验要求 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O. ...
- Android之网络编程
本文主要包括三方面内容 Httpurlconnection中doGet与doPost方法实现提交数据到服务器 HttpClient中doGet与doPost方法实现提交数据到服务器 android-a ...
- svn status 显示 ~xx
“~” 版本控制下的项目与其它类型的项目重名
- mysql多实例(个人的情况,不是大众的)里面有配置好的脚本+主从复制
[root@DB-S ~]# ll /usr/local/|grep mysql lrwxrwxrwx. 1 root root 21 Jun 14 01:52 mysql -> /alidat ...