【BZOJ1901】Dynamic Rankings [整体二分]
Dynamic Rankings
Time Limit: 10 Sec Memory Limit: 128 MB
[Submit][Status][Discuss]
Description
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。
Input
第一行有两个正整数
分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n]。
接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。
Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
Output
Sample Input
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
6
HINT
m,n≤10000 , 0≤ai≤1e9。
Main idea
询问区间中第k小的数是多少,需要支持单点修改点的权值。
Solution
我们看到这道题,发现对于一个询问应该是可以二分查找答案的,那么我们从整体二分的角度来思考。
我们发现,如果没有修改的话,显然很简单,直接整体二分将所有询问一起操作即可。
但是我们有操作,那应该怎么办呢?
我们对于每一次修改,记录一下原来的值,简单来说,就是对于每一次操作,记录一下若opt=1,则表示这个点在这个状态的值;若opt=3,则表示这是一个询问,
我们对于修改来说,新增一个opt=2,表示在修改之前的值。也就是说,我们在执行一个区间的操作时,如果发现一个opt=2,那么之前一定有一个一样的值的opt为1,并且其已经对答案造成影响,现在那个元素已经被修改了,就要相应地减去它之前对答案的影响,这样就完成了修改。
然后我们整体二分权值,像静态查询kth那样修改一下即可。思路一气呵成 \(≧▽≦)/
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<map>
using namespace std; const int ONE=;
const int INF=1e9+; int n,m;
int x,y,k;
char ch[];
int cnt,Num;
int a[ONE],record[ONE];
int Ans[ONE]; struct power
{
int opt,cnt;
int l,r,k;
int pos,value;
int cur;
}oper[ONE],qL[ONE],qR[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} namespace Bit
{
struct power
{
int value;
}Node[ONE]; int lowbit(int i)
{
return i&-i;
} void Update(int R,int x)
{
for(int i=R;i<=n;i+=lowbit(i))
Node[i].value+=x;
} int Query(int R)
{
int res=;
for(int i=R;i>=;i-=lowbit(i))
res+=Node[i].value;
return res;
}
} void Solve(int l,int r,int L,int R)
{
if(l>r) return;
if(L==R)
{
for(int i=l;i<=r;i++)
if(oper[i].opt==)
Ans[oper[i].cnt] = L;
return;
} int M=(L+R)>>;
for(int i=l;i<=r;i++)
{
if(oper[i].opt== && oper[i].value<=M)
Bit::Update(oper[i].pos,);
if(oper[i].opt== && oper[i].value<=M)
Bit::Update(oper[i].pos,-);
if(oper[i].opt==)
record[i]=Bit::Query(oper[i].r) - Bit::Query(oper[i].l-);
} for(int i=l;i<=r;i++)
{
if(oper[i].opt== && oper[i].value<=M)
Bit::Update(oper[i].pos,-);
if(oper[i].opt== && oper[i].value<=M)
Bit::Update(oper[i].pos,);
} int l_num=,r_num=;
for(int i=l;i<=r;i++)
{
if(oper[i].opt!=)
{
if(oper[i].value <= M)
qL[++l_num]=oper[i];
else
qR[++r_num]=oper[i];
}
else
{
if(oper[i].cur + record[i] >= oper[i].k)
qL[++l_num]=oper[i];
else
{
qR[++r_num]=oper[i];
qR[r_num].cur+=record[i];
}
}
} int t=l;
for(int i=;i<=l_num;i++) oper[t++]=qL[i];
for(int i=;i<=r_num;i++) oper[t++]=qR[i]; Solve(l,l+l_num-,L,M);
Solve(l+l_num,r,M+,R);
} int main()
{
n=get(); m=get();
for(int i=;i<=n;i++)
{
a[i]=get();
oper[++cnt].opt=; oper[cnt].pos=i; oper[cnt].value=a[i];
} for(int i=;i<=m;i++)
{
scanf("%s",ch);
if(ch[]=='Q')
{
x=get(); y=get(); k=get();
oper[++cnt].opt=; oper[cnt].l=x; oper[cnt].r=y; oper[cnt].k=k;
oper[cnt].cnt=++Num;
}
else
{
x=get(); y=get();
oper[++cnt].opt=; oper[cnt].pos=x; oper[cnt].value=a[x];
oper[++cnt].opt=; oper[cnt].pos=x; oper[cnt].value=y;
a[x]=y;
}
} Solve(,cnt,,INF); for(int i=;i<=Num;i++)
printf("%d\n",Ans[i]);
}
【BZOJ1901】Dynamic Rankings [整体二分]的更多相关文章
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9094 Solved: 3808[Submit][Status][Discuss] Descript ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——整体二分
[题目分析] 上次用树状数组套主席树做的,这次用整体二分去水. 把所有的查询的结果一起进行二分,思路很好. [代码] #include <cstdio> #include <cstr ...
- ZOJ2112 Dynamic Rankings(整体二分)
今天学习了一个奇技淫巧--整体二分.关于整体二分的一些理论性的东西,可以参见XRH的<浅谈数据结构题的几个非经典解法>.然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如 ...
- BZOJ 1901 Dynamic Rankings (整体二分+树状数组)
题目大意:略 洛谷传送门 这道题在洛谷上数据比较强 貌似这个题比较常见的写法是树状数组套主席树,动态修改 我写的是整体二分 一开始的序列全都视为插入 对于修改操作,把它拆分成插入和删除两个操作 像$C ...
- 洛谷$P2617\ Dynamic\ Rankings$ 整体二分
正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...
- BZOJ.1901.Dynamic Rankings(整体二分)
题目链接 BZOJ 洛谷 (以下是口胡) 对于多组的询问.修改,我们可以发现: 假设有对p1,p2,p3...的询问,在这之前有对p0的修改(比如+1),且p0<=p1,p2,p3...,那么我 ...
- [主席树]ZOJ2112 && BZOJ1901 Dynamic Rankings
题意:n个数,q个询问 (n<=50000, q<=10000) Q x y z 代表询问[x, y]区间里的第z小的数 C x y 代表将(从左往右数)第x个数变成y 上篇介绍了在 ...
- BZOJ1901 - Dynamic Rankings(树状数组套主席树)
题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t 要求你把第i个数修改为t 题解 动态的区间第k ...
随机推荐
- Android Stadio调试gradle 插件 || Android Stadio 远程调试 || Anroid APT调试
有时候,自己开发了gralde插件,想调试一下.毕竟打印log 成本太高.效率太低.怎么做呢? 第一种方法: 1.执行gradlew 命令的时候,加上几个参数:-Dorg.gradle.debug=t ...
- Can’t delete list item in Sharepoint2013
Today,I have meet a very strange error.When I attempt to delete a item from a list,I recieve an ...
- Unity5.6偶尔不能创建项目解决办法
Unity5.6偶尔启动后,不能创建项目,解决办法如下: 1.打开Unity 2.在开始窗口退出当前登录的账户 3.重新登录 4.然后就可以创建新项目了 5.如果以上方法不生效,关闭Unity再重试一 ...
- php用GD库给图片添加水印
php用GD库给图片添加文字水印,整个代码比较简单,DEMO如下: <?php /*打开图片*/ //1.配置图片路径 $src = "aeroplane.jpg"; //2 ...
- 阅读MDN文档之布局(四)
Introducing positioning Static positioning Relative positioning Introducing top, bottom, left and ri ...
- 局部敏感哈希LSH
之前介绍了Annoy,Annoy是一种高维空间寻找近似最近邻的算法(ANN)的一种,接下来再讨论一种ANN算法,LSH局部敏感哈希. LSH的基本思想是: 原始空间中相邻的数据点通过映射或投影变换后, ...
- 解决:Unable to execute dex: GC overhead limit exceeded
转自http://blog.sina.com.cn/s/blog_6e334dc70101hnug.html Android打包时下面的错误: Unable to execute dex: GC ov ...
- 在线算法&离线算法
[在线算法] 定义:指用户每输入一个查询便马上处理一个查询.该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询. 常见在线算法:ST算法 [离线算法] 定义:
- 面试题中经常遇到的SQL题:删除重复数据,保留其中一条
如题,解决思路如下: 1.首先我们需要找出拥有重复数据的记录 ---以name字段分组 select Name,COUNT(Name) as [count] from Permission group ...
- 文本太长,用省略号显示的css样式
——html代码 <divid="d1" title="鼠标放上显示的文字"></div> ——css代码 #d1{ width:300 ...