【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 ...
随机推荐
- vi编辑图
vi使用方法
- python 基础篇 04(列表 元组 常规操作)
本节主要内容:1. 列表2. 列表的增删改查3. 列表的嵌套4. 元组和元组嵌套5. range 一. 列表1.1 列表的介绍列表是python的基础数据类型之一 ,其他编程语言也有类似的数据类型. ...
- 剑指offer-变态跳台阶09
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. class Solution: def jumpFloorII(self, n ...
- 九度OJ--1164(C++)
#include <iostream>#include <vector> using namespace std; int main() { int n; // n为矩阵阶数 ...
- Leetcode 674.最长递增序列
最长递增序列 给定一个未经排序的整数数组,找到最长且连续的的递增序列. 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3. 尽管 [1,3 ...
- LeetCode 81——搜索旋转排序数组 II
1. 题目 2. 解答 2.1. 方法一 基于 LeetCode 33--搜索旋转排序数组 中的方法二. 当 nums[mid] = nums[right] 时,比如 [1, 1, 2, 1, 1], ...
- [转]dwr3框架学习笔记--简介及原理简介
1.DWR简介 DWR(直接web远程访问),DWR是一个Java库,使服务器上的Java和JavaScript的浏览器进行交互和相互调用尽可能简单. DWR 是一个可以允许你去创建 AJAX WEB ...
- 福大软工1816:Alpha(2/10)
Alpha 冲刺 (2/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1.学习qqbot库: 2.实 ...
- bbbbbeta
about beta 写在开头:(小声bb,无任何专业知识) 好了正文开始了 = = beta冲刺对于来说可能是让我觉得非常有成就感的叭,相比于alpha,每天都能写代码的感觉真好鸭(认真脸)(虽然天 ...
- SSH答疑解惑系列(一)——spring容器是如何启动的
SSH框架十分受欢迎,其中有一个原因就是spring可以和Struts2框架无缝整合.在使用spring时,无需手动创建web容器,而是通过配置文件声明式创建spring容器. 在web应用中,创建s ...