[Tyvj 1730] 二逼平衡树
先来一发题面QwQ
[TYVJ1730]二逼平衡树
Time Limit:2 s Memory Limit:512 MB
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 5Sample Output
2
4
3
4
9Hint
n,m<=50000 保证有序序列所有值在任何时刻满足[0,10^8]但是询问的数未必
这题正解似乎是树套树(线段树套平衡树)
然而我用分块大法水过去了233
分块的话思路还是比较明确的,比如对于求排名操作(操作1),对于两端的块我们可以选择直接暴力查询比$key$值小的值的个数,中间的完整块可以选择二分查找($std::lower\_bound$)来得出比$key$小的元素个数,累加起来加上1就是答案了.
求K大的话比较麻烦,要二分第K大的值然后用求排名操作来检验...
修改直接暴力修改不解释
前驱/后继则可以用上面求排名的方式来查找,不同的是对于比$key$小/大的元素不应累加而是求最大/小值.
然后就到了袋马时间~(突然感觉好草率啊QwQ)
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> const int MAXN=;
const int MAXB=;
const int INF=0x7FFFFFFF; int n,m;
int endSize;
int blockNum;
int blockSize;
int data[MAXN];
int block[MAXN][MAXB]; void Initialize();
void FastRead(int&);
void Modify(int,int);
int Kth(int,int,int);
int Rank(int,int,int);
int Predecessor(int,int,int);
int Successor(int,int,int); int main(){
int opt,l,r,num;
Initialize();
for(int i=;i<m;i++){
scanf("%d",&opt);
if(opt==){
FastRead(l);
FastRead(r);
FastRead(num);
printf("%d\n",Rank(l-,r-,num));
}
else if(opt==){
FastRead(l);
FastRead(r);
FastRead(num);
printf("%d\n",Kth(l-,r-,num));
}
else if(opt==){
FastRead(l);
FastRead(num);
Modify(l-,num);
}
else if(opt==){
FastRead(l);
FastRead(r);
FastRead(num);
printf("%d\n",Predecessor(l-,r-,num));
}
else{
FastRead(l);
FastRead(r);
FastRead(num);
printf("%d\n",Successor(l-,r-,num));
}
}
return ;
} inline int Rank(int l,int r,int key){
int lb=l/blockSize;
int rb=r/blockSize;
int ans=;
if(lb==rb){
for(int i=l;i<=r;i++){
if(data[i]<key){
ans++;
}
}
}
else{
for(int i=l;i<(lb+)*blockSize;i++){
if(data[i]<key){
ans++;
}
}
for(int i=rb*blockSize;i<=r;i++){
if(data[i]<key){
ans++;
}
}
for(int i=lb+;i<rb;i++){
ans+=std::lower_bound(block[i],block[i]+blockSize,key)-block[i];
}
}
return ans;
} inline int Kth(int l,int r,int pos){
int L=-;
int R=;
while(R-L>){
int mid=(L+R)>>;
if(Rank(l,r,mid)>pos)
R=mid;
else
L=mid;
}
return R-;
} inline void Modify(int pos,int key){
if(data[pos]==key)
return;
int* thisBlock=block[pos/blockSize];
int old=data[pos];
int size=(pos/blockSize)==blockNum?endSize:blockSize;
data[pos]=key;
pos=std::lower_bound(thisBlock,thisBlock+size,old)-thisBlock;
thisBlock[pos]=key;
std::sort(thisBlock,thisBlock+size);
} inline int Predecessor(int l,int r,int key){
int lb=l/blockSize;
int rb=r/blockSize;
int ans=-INF;
if(lb==rb){
for(int i=l;i<=r;i++){
if(data[i]<key)
ans=std::max(ans,data[i]);
}
}
else{
for(int i=l;i<(lb+)*blockSize;i++){
if(data[i]<key)
ans=std::max(ans,data[i]);
}
for(int i=rb*blockSize;i<=r;i++){
if(data[i]<key)
ans=std::max(ans,data[i]);
}
for(int i=lb+;i<rb;i++){
int pos=std::lower_bound(block[i],block[i]+blockSize,key)-block[i];
if(pos>)
ans=std::max(ans,block[i][pos-]);
}
}
return ans;
} inline int Successor(int l,int r,int key){
int lb=l/blockSize;
int rb=r/blockSize;
int ans=INF;
if(lb==rb){
for(int i=l;i<=r;i++)
if(data[i]>key)
ans=std::min(ans,data[i]);
}
else{
for(int i=l;i<(lb+)*blockSize;i++){
if(data[i]>key)
ans=std::min(ans,data[i]);
}
for(int i=rb*blockSize;i<=r;i++){
if(data[i]>key)
ans=std::min(ans,data[i]);
}
for(int i=lb+;i<rb;i++){
int pos=std::upper_bound(block[i],block[i]+blockSize,key)-block[i];
if(pos<blockSize)
ans=std::min(ans,block[i][pos]);
}
}
return ans;
} void Initialize(){
#ifndef ASC_LOCAL
freopen("psh.in","r",stdin);
freopen("psh.out","w",stdout);
#endif
FastRead(n);
FastRead(m);
blockSize=sqrt(n);
for(int i=;i<n;i++){
FastRead(data[i]);
block[blockNum][endSize]=data[i];
if(++endSize==blockSize){
blockNum++;
endSize=;
}
}
for(int i=;i<blockNum;i++)
std::sort(block[i],block[i]+blockSize);
if(endSize!=)
std::sort(block[blockNum],block[blockNum]+endSize);
} inline void FastRead(int& target){
target=;
register char ch=getchar();
bool neg=false;
while(!isdigit(ch)){
if(ch=='-')
neg=true;
ch=getchar();
}
while(isdigit(ch)){
target=target*+ch-'';
ch=getchar();
}
if(neg)
target=-target;
}
Backup: Block Search
然后图包时间233(拿图至少评论一下吼不吼哇QwQ)

[Tyvj 1730] 二逼平衡树的更多相关文章
- 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.... -------------------------------------------------------------------- ...
- bzoj3196: Tyvj 1730 二逼平衡树 树套树
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...
- 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 二逼平衡树
树套树 Orz zyf 学(co)习(py)了一下树套树的写法,嗯……就是线段树套平衡树. 具体实现思路就是:外部查询用的都是线段树,查询内部自己调用平衡树的操作. 抄抄代码有助理解= = 八中挂了… ...
- 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树
线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...
- [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树
题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...
- BZOJ3196: Tyvj 1730 二逼平衡树
传送门 主席树的常数蜜汁优越,在BZOJ上跑了rnk1. 做法很简单,主席树套BIT. 1-3做法很简单,第四个和第五个做法转换成前两个就行了. //BZOJ 3196 //by Cydiater / ...
随机推荐
- Bash的条件表达式求值
Bash的条件控制允许两种类型:1)命令的成功或失败 2)逻辑表达式的真假这两种类型都可以通过退出状态($?)来检验,$?=0为真,否则为假 一.命令的成功或失败 通过查看$?值$echo $? 二. ...
- guoshiyv 数据结构与算法2-1 线性链式存储
线性链式存储: 包含两部分:1.存储的单个元素 2.指针,指向下一个的地址 typedef struct() { ElementType Data; struct Node *Next; }Lis ...
- python 标准库 -- pickle & cPickle
pickle & cPickle pickle 和 cPickle 除了导入名称不一样之外, 使用方法, 均一样. pickle 导入 import pickle cPickle 导入 imp ...
- Vin码识别(车架号识别)技术,摆脱手动录入提高工作效率
本文主题:Vin码识别(车架号识别)技术,摆脱手动录入提高工作效率 本文关键词:Vin码识别,汽车Vin码识别,车架号识别,汽车车架号识别,车代码识别,车代号识别 本文主旨:一.Vin码(车架号)在什 ...
- Kafka官方文档翻译——实现
IMPLEMENTATION 1. API Design Producer APIs Producer API封装了底层两个Producer: kafka.producer.SyncProducer ...
- 详解 RAC 中各种IP和监听的意义
一.SCAN 概念 SCAN(Single Client Access Name)是 Oracle从11g R2开始推出的,客户端可以通过 SCAN 特性负载均衡地连接到 RAC数据库 SCAN 最明 ...
- C#—泛型_推迟一切可以推迟的东西
泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...
- mac下git配置和jenkins打包
今天自己配置了下jenkins,还算是比较顺利,把整个过程和大家分享下. 1. 查看秘钥是否存在 打开终端查看是否已经存在SSH密钥:cd ~/.ssh 如果没有密钥则不会有此文件夹,有则备份删除, ...
- Java多线程(一) —— 线程的状态详解
一.多线程概述 1. 进程 是一个正在执行的程序.是程序在计算机上的一次运行活动. 每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 系统以进程为基本单位进行系统资源的调度 ...
- 利用CSS3新特性实现完全兼容的自定义滚动条。
背景:最近项目里面因为统一页面风格,用到了自定义滚动条,在完成之前的那个滚动条的时候,与网上各个滚动条插件实现的方法类似,相当于造了轮子,通过css3的 网上看到的滚动条插件多数是通过监听内容的滚动事 ...