先来一发题面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 5

Sample Output

2
4
3
4
9

Hint

n,m<=50000   保证有序序列所有值在任何时刻满足[0,10^8]但是询问的数未必

这题正解似乎是树套树(线段树套平衡树)

然而我用分块大法水过去了233

分块的话思路还是比较明确的,比如对于求排名操作(操作1),对于两端的块我们可以选择直接暴力查询比$key$值小的值的个数,中间的完整块可以选择二分查找($std::lower\_bound$)来得出比$key$小的元素个数,累加起来加上1就是答案了.

求K大的话比较麻烦,要二分第K大的值然后用求排名操作来检验...

修改直接暴力修改不解释

前驱/后继则可以用上面求排名的方式来查找,不同的是对于比$key$小/大的元素不应累加而是求最大/小值.

然后就到了袋马时间~(突然感觉好草率啊QwQ)

GitHub:BlockSearch

 #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] 二逼平衡树的更多相关文章

  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 二逼平衡树( 树套树 )

    这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...

  3. bzoj3196: Tyvj 1730 二逼平衡树 树套树

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...

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

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

  5. bzoj 3196: Tyvj 1730 二逼平衡树

    #include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...

  6. 【BZOJ】【3196】Tyvj 1730 二逼平衡树

    树套树 Orz zyf 学(co)习(py)了一下树套树的写法,嗯……就是线段树套平衡树. 具体实现思路就是:外部查询用的都是线段树,查询内部自己调用平衡树的操作. 抄抄代码有助理解= = 八中挂了… ...

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

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

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

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

  9. BZOJ3196: Tyvj 1730 二逼平衡树

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

随机推荐

  1. 关于数据库优化1——关于count(1),count(*),和count(列名)的区别,和关于表中字段顺序的问题

    1.关于count(1),count(*),和count(列名)的区别 相信大家总是在工作中,或者是学习中对于count()的到底怎么用更快.一直有很大的疑问,有的人说count(*)更快,也有的人说 ...

  2. FullCalendar 日历插件中文说明文档

    FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...

  3. Ubuntu17.04配置LNMP(Nginx+PHP7+MySQL)简单教程 快速 易学 简单易懂

    我安装的是当前最新的Ubuntu版本17.04,在虚拟机中先试用一下,如果没有什么不稳定的现象,准备以后作为主力操作系统 Ubuntu属于Debian系的Linux系统,拥有着一个很NB的软件包管理器 ...

  4. A. Karen and Morning

    A. Karen and Morning time limit per test 2 seconds  memory limit per test 512 megabytes input standa ...

  5. CSS实现两端对齐效果

    CSS实现两端对齐效果 两端对齐,从概念上来说,其实不难理解.如果不明白什么叫两端对齐,可以玩玩word等办公软件. 下面谈谈如何实现文本的两端对齐.我所知道的大概有以下几种方法 text-align ...

  6. 在C#中初遇Socket - 1

    后期项目实战:多人在线聊天室 源码位置:https://git.oschina.net/z13qu/BlogProjects 课前须知 这里不讲解Socket和TCP/IP的底层知识 对于初学者来说底 ...

  7. 字符串数组与字符串之间的互转(join/split)

    1.Java 1-1.字符串数组=>字符串:StringUtils: join(Object[] array, String separator) 例: Java代码 收藏代码 import o ...

  8. iOS10 相关的隐私设置,

    最近下载了几个demo,总是一运行就崩,看了下崩溃日志,有几个是因为没在plist里设置因此权限,而现在iOS 10 开始对隐私权限更加严格, 如需使用隐私权限需要在工程的info.plist文件中声 ...

  9. Disruptor的应用示例——大文件拆分

    结合最近Disruptor的学习,和之前一直思考解决的大文件拆分问题,想到是否可以使用Disruptor作为生产者/消费者传递数据的通道呢?借助其高效的传递,理论上应当可以提升性能.此文便是此想法的落 ...

  10. 可满足性模块理论(SMT)基础 - 01 - 自动机和斯皮尔伯格算术

    可满足性模块理论(SMT)基础 - 01 - 自动机和斯皮尔伯格算术 前言 如果,我们只给出一个数学问题的(比如一道数独题)约束条件,是否有程序可以自动求出一个解? 可满足性模理论(SMT - Sat ...