[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 / ...
随机推荐
- 整理一些提高C#编程性能的技巧
1.使用StringBuilder代替使用string 连接符 "+" 说明:String类对象是不可变的(只读),一旦创建该对象,就不能修改该对象的值. 对象String对象的重 ...
- DataTable数据导出Excel 并且下载
public string Excel(System.Data.DataTable dt) { //模板的路径 string strUploadPath = HttpContext.Current.S ...
- GIS与水文分析(1)GIS与水文学
GIS与水文分析(1)GIS与水文学 对于大部分GIS从业人员或者利用GIS作为研究方向的人员来说,水文学过于专业,更偏重于理论化,很难从GIS的角度来模拟和分析水文的过程.这其实是个普遍性的问题,任 ...
- python 标准库 -- unittest
一. unittest 单元测试 编写单元测试 示例代码 : import unittest from flask import current_app from app import create_ ...
- PHP中单引号和双引号的区别
双引号里面的字段会经过编译器解释,然后再当作HTML代码输出:单引号里面的不进行解释,直接输出: PHP引号使用原则 1.字符串的值用单引号 2.PHP中尽量用单引号,HTML代码全部用双引号 3.在 ...
- css透明度的设置
Css代码 .transparent_class { filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: ...
- ECSHOP购物车页面显示商品简单描述
1.这里说的商品简单描述,不是商品的详细信息,而是后台编辑商品时在“其他信息”标签栏填写的那个“商品简单描述”,即goods_brief字段 2.修改lib_order.php文件的get_cart_ ...
- SICP-1.7-递归函数
递归函数 函数内部直接或间接的调用函数自身 将复杂问题简单化 例子程序 def sum_digits(n): """Return the sum of the digit ...
- 通过位异或来交换a,b的值和通过中间变量交换a,b的值
//通过位异或来交换a,b的值 #include <stdio.h> int main(int argc, const char * argv[]) { int a=20,b=10; ...
- salesforce零基础学习(七十四)apex:actionRegion以及apex:actionSupport浅谈
我们在开发中,很难会遇见不提交表单的情况.常用的apex:commandButton,apex:commandLink,apex:actionFunction,apex:actionSupport.他 ...