【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 ...
随机推荐
- model的index无限次数执行导致stackOverFlow
model的index无限次数执行导致stackOverFlow
- 在Linux上进行mySql安装部署及遇到的问题的解决方法
前提: Linux centOS虚拟机64位 1.首先确认是否已安装过MySQL 方法一:删除原有的MySQL目录: 使用查找语句: whereis mysql find / -name mysql ...
- npm命令 VS yarn命令
npm yarn 说明 npm init yarn init 在项目中引导创建一个package.json文件 npm install yarn install/yarn 安装所有依赖包(依据pa ...
- JMeter学习笔记(九) 参数化4--User Variables
4.User Variables 用户参数 1)线程组右键添加 -> 前置处理器 -> 用户参数 2)配置用户参数 3)添加HTTP请求,引用用户参数,格式: ${} 4)配置线程数 5) ...
- fiddler抓包-简单易操作(一)
1.下载fiddler 可以到fiddler官网去下,网址:https://www.telerik.com/download/fiddler 下载完成后,安装即可. 2.运行fiddler,进入fid ...
- Leetcode 3. Longest Substring Without Repeating Characters (Medium)
Description Given a string, find the length of the longest substring without repeating characters. E ...
- ajax 异步刷新,需要填写的参数
参数 options 类型:Object 可选.AJAX 请求设置.所有选项都是可选的. ******* async 类型:Boolean 默认值: true.默认设置下,所有请求均为异步请求.如果需 ...
- 常用的gif加载动态图片
精心搜集的网页素材,包括:Loading GIF动画,"正在加载中"小图片,"请等待"小图标等,欢迎您的下载. 提示:点击鼠标右键,选择”图片另存为“即可轻松保 ...
- 简单java采集程序一
[目标任务]通过该网站采集全国的手机号码段至数据库表中 [完成过程] 1.初涉正则表达式,学会写简单的正则表达式 2.获取单个网页内容,学会java中基本的IO流 3.将获取数据插入mysql数据库表 ...
- esayui combotree 只能选择子节点
esayui combotree 只能选择子节点用onBeforeSelect:参数是node,节点被选中之前触发,返回false取消选择动作. 网上找了好多都没一个可用的,要想知道他是子节点还是根节 ...