高级数据结构(树状数组套主席树):ZOJ 2112 Dynamic Rankings
Dynamic Rankings
Time Limit: 10 Seconds Memory Limit: 32768 KB
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.
Your task is to write a program for this computer, which
- Reads N numbers from the input (1 <= N <= 50,000)
- Processes M instructions of the input (1 <= M <= 10,000). These instructions
include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change
some a[i] to t.
Input
The first line of the input is a single number X (0 < X <= 4), the number
of the test cases of the input. Then X blocks each represent a single test case.
The first line of each block contains two integers N and M, representing N numbers
and M instruction. It is followed by N lines. The (i+1)-th line represents the
number a[i]. Then M lines that is in the following format
Q i j k or
C i t
It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change
some a[i] to t, respectively. It is guaranteed that at any time of the operation.
Any number a[i] is a non-negative integer that is less than 1,000,000,000.
There're NO breakline between two continuous test cases.
Output
For each querying operation, output one integer to represent the result. (i.e.
the k-th smallest number of a[i], a[i+1],..., a[j])
There're NO breakline between two continuous test cases.
Sample Input
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
3
6
不知道为何,ZOJ上交这道题要FQ,BZOJ上有这道题,还TM是权限题,估计是偷的(鄙视BZOJ)。
因为有修改操作,考虑保持原有的主席树结构,假设i位置上的数变化,那么要修改主席树中i及i以后的位置,如果一个一个修改肯定超时,可以考虑将修改的时间摊到查询上去,用Bit维护修改操作,记为前缀和,很好脑补。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=;
const int maxm=;
int tot,cnt,hash[maxn],a[maxn];
int sum[maxm],ch[maxm][],rt[maxn],bit[maxn];
int use[maxn],n;
struct Ask{
int l,r,k;
}q[maxn]; void Insert(int pre,int &rt,int l,int r,int g,int d){
rt=++cnt;
ch[rt][]=ch[pre][];
ch[rt][]=ch[pre][];
sum[rt]=sum[pre]+d;
if(l==r)return;
int mid=(l+r)>>;
if(mid>=g)Insert(ch[pre][],ch[rt][],l,mid,g,d);
else Insert(ch[pre][],ch[rt][],mid+,r,g,d);
} void Modify(int p,int g,int d){
while(p<=n){
Insert(bit[p],bit[p],,tot,g,d);
p+=p&(-p);
}
} int Query(int pre,int rt,int l,int r,int k,int L,int R){
if(l==r)return l;
int mid=(l+r)>>,p=R,c=;
while(p){c+=sum[ch[use[p]][]];p-=p&(-p);}p=L-;
while(p){c-=sum[ch[use[p]][]];p-=p&(-p);}
c+=sum[ch[rt][]]-sum[ch[pre][]];
if(c>=k){
p=R;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}p=L-;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}
return Query(ch[pre][],ch[rt][],l,mid,k,L,R);
}
else{
k-=c;p=R;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}p=L-;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}
return Query(ch[pre][],ch[rt][],mid+,r,k,L,R);
} } int Solve(int l,int r,int k){
int p=l-;
while(p){use[p]=bit[p];p-=p&(-p);}p=r;
while(p){use[p]=bit[p];p-=p&(-p);}
return Query(rt[l-],rt[r],,tot,k,l,r);
} void Init(){
memset(rt,,sizeof(rt));cnt=;
memset(bit,,sizeof(bit));
} bool cmp(int a,int b){
return a>b;
}
char op[];
int main(){
int T,Q;
scanf("%d",&T);
while(T--){
Init();
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
tot=n;
for(int i=;i<=Q;i++){
scanf("%s",op);
if(op[]=='Q')
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
else{
scanf("%d%d",&q[i].l,&q[i].k);
a[++tot]=q[i].k;q[i].r=-;
}
}
for(int i=;i<=tot;i++)
hash[i]=a[i];
sort(hash+,hash+tot+);
for(int i=;i<=tot;i++)
a[i]=lower_bound(hash+,hash+tot+,a[i])-hash; for(int i=;i<=n;i++)
Insert(rt[i-],rt[i],,tot,a[i],);
for(int i=,head=n;i<=Q;i++){
if(q[i].r==-){
Modify(q[i].l,a[q[i].l],-);
Modify(q[i].l,a[++head],);
a[q[i].l]=a[head];
}
else
printf("%d\n",hash[Solve(q[i].l,q[i].r,q[i].k)]);
}
}
return ;
}
2016年6月9日重打了一遍……
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
const int maxm=;
char op[];
int n,Q,T,use[maxn];
int qa[maxn],qb[maxn],qk[maxn];
int tot,cnt,ch[maxm][],sum[maxm];
int a[maxn],hash[maxn],bit[maxn],rt[maxn];
void Insert(int pre,int &rt,int l,int r,int g,int d){
rt=++cnt;
ch[rt][]=ch[pre][];
ch[rt][]=ch[pre][];
sum[rt]=sum[pre]+d;
if(l==r)return;
if(l+r>>>=g)Insert(ch[pre][],ch[rt][],l,l+r>>,g,d);
else Insert(ch[pre][],ch[rt][],(l+r>>)+,r,g,d);
}
void Modify(int p,int g,int d){
while(p<=n){
Insert(bit[p],bit[p],,tot,g,d);
p+=p&(-p);
}
}
int Query(int pre,int rt,int l,int r,int k,int L,int R){
if(l==r)return l;
int c=sum[ch[rt][]]-sum[ch[pre][]],p=R;
while(p){c+=sum[ch[use[p]][]];p-=p&(-p);}p=L-;
while(p){c-=sum[ch[use[p]][]];p-=p&(-p);}
if(c>=k){p=R;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}p=L-;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}
return Query(ch[pre][],ch[rt][],l,l+r>>,k,L,R);
}
else{p=R;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}p=L-;
while(p){use[p]=ch[use[p]][];p-=p&(-p);}
return Query(ch[pre][],ch[rt][],(l+r>>)+,r,k-c,L,R);
}
}
int Solve(int i){
int p=qb[i];
while(p){use[p]=bit[p];p-=p&(-p);}p=qa[i]-;
while(p){use[p]=bit[p];p-=p&(-p);}
return Query(rt[qa[i]-],rt[qb[i]],,tot,qk[i],qa[i],qb[i]);
}
void Init(){
memset(bit,,sizeof(bit));
cnt=;tot=n;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("dynrank.in","r",stdin);
freopen("dynrank.out","w",stdout);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&Q);Init();
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
hash[i]=a[i];
}
for(int i=;i<=Q;i++){
scanf("%s",op);
if(op[]=='Q')scanf("%d%d%d",&qa[i],&qb[i],&qk[i]);
else{
scanf("%d%d",&qa[i],&qk[i]);
tot++;hash[tot]=a[tot]=qk[i];qb[i]=-;
}
}
sort(hash+,hash+tot+);
for(int i=;i<=tot;i++)
a[i]=lower_bound(hash+,hash+tot+,a[i])-hash;
for(int i=;i<=n;i++)Insert(rt[i-],rt[i],,tot,a[i],);
for(int i=,p=n;i<=Q;i++){
if(qb[i]==-){
Modify(qa[i],a[qa[i]],-);
Modify(qa[i],a[++p],);
a[qa[i]]=a[p];
}
else
printf("%d\n",hash[Solve(i)]);
}
}
return ;
}
还打了一个强大的整体二分。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
int T,n,Q,cntQ;
int num[maxn],ans[maxn],bit[maxn];
char op[];
struct Node{
int x,y,k,id,tp;
}a[maxn],t1[maxn],t2[maxn];
//tp==1 add; tp==2 del; tp==3 query; void Add(int x,int d){
while(x<=n){
bit[x]+=d;
x+=x&(-x);
}
} int Query(int x){
int ret=;
while(x){
ret+=bit[x];
x-=x&(-x);
}
return ret;
} void Solve(int h,int t,int l,int r){
if(l==r){
for(int i=h;i<=t;i++)
if(a[i].tp==)ans[a[i].id]=l;
return;
}
if(h>t)return;
int p1=,p2=,d;
for(int i=h;i<=t;i++){
if(a[i].tp==){
d=Query(a[i].y)-Query(a[i].x-);
if(d>=a[i].k)t1[++p1]=a[i];
else{
a[i].k-=d;
t2[++p2]=a[i];
}
}
else if(a[i].k<=l+r>>){
if(a[i].tp==)Add(a[i].x,);
if(a[i].tp==)Add(a[i].x,-);
t1[++p1]=a[i];
}
else t2[++p2]=a[i];
}
for(int i=h;i<=t;i++){
if(a[i].k<=l+r>>){
if(a[i].tp==)Add(a[i].x,-);
if(a[i].tp==)Add(a[i].x,);
}
}
for(int i=;i<=p1;i++)a[h+i-]=t1[i];
for(int i=;i<=p2;i++)a[h+i+p1-]=t2[i];
Solve(h,h+p1-,l,l+r>>);
Solve(h+p1,t,(l+r>>)+,r);
} int main(){
#ifndef ONLINE_JUDGE
freopen("dynrank.in","r",stdin);
freopen("dynrank.out","w",stdout);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++){
scanf("%d",&a[i].k);
a[i].x=i;a[i].tp=;
num[i]=a[i].k;
}
cntQ=;
int x,y,k;
while(Q--){
scanf("%s",op);
if(op[]=='Q'){
scanf("%d%d%d",&x,&y,&k);
a[++n].id=++cntQ;a[n].tp=;
a[n].x=x;a[n].y=y;a[n].k=k;
}
else{
scanf("%d%d",&x,&k);
a[++n].tp=;a[n].x=x;a[n].k=num[x];
a[++n].tp=;a[n].x=x;a[n].k=k;num[x]=k;
}
}
Solve(,n,,);
for(int i=;i<=cntQ;i++)
printf("%d\n",ans[i]);
}
return ;
}
高级数据结构(树状数组套主席树):ZOJ 2112 Dynamic Rankings的更多相关文章
- BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树
BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- P2617 Dynamic Rankings(树状数组套主席树)
P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...
- [COGS257]动态排名系统 树状数组套主席树
257. 动态排名系统 时间限制:5 s 内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】
题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
随机推荐
- 导出到excel
/// <summary> /// 导出 /// </summary> /// <param name="table">数据表</para ...
- js分家效应
(原创文章,转载请注明出处) 有继承,那么就有分家.让我们看以下例子. var parents = function(){ } parents.prototype.money = 200; var c ...
- KTV2
自制KTV点歌系统经验 重唱与切歌 1.重唱 这个简单,会了播放,就会了这个; 我们用的数组下标来确定播放歌曲,自然如果下标没变的话,那播放的就还是这首了.所以只要确定了要执行的命令是重唱就行了. 那 ...
- 找出整数中第k大的数
一 问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二 举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...
- SGU 195. New Year Bonus Grant
时间限制:0.75s 空间限制:4M 题意: 在一颗树(最多500000个节点)中,可以对节点染色,但是一个节点染了色后,它的父节点和兄弟节点都不能再染了,求最大的染色节点数,并输出所有染色节点. S ...
- chdir 改变当前目录为起始目录
<?php chdir(dirname(__FILE__));//把当前目录设置为当前目录?> 将 PHP 的当前目录改为 directory. 参数 directory 新的当前目录 返 ...
- MVC Unit Testing学习笔记
MVC Unit Testing 参考文档: 1.http://www.asp.net/mvc/overview/testing 2.http://www.asp.net/mvc/tutorials/ ...
- PHP框架_ThinkPHP基础
目录 1.ThinkPHP项目结构 2.ThinkPHP运行流程 3.ThinkPHP配置文件 4.ThinkPHP四种URL模式 5.ThinkPHP用户自定义函数 6.ThinkPHP模板展示及变 ...
- django-orm-standalone
django-orm-standalone script via:https://github.com/masnun/django-orm-standalone/ # Django specific ...
- Python新手学习基础之初识python——与众不同2
看完了Python的缩进,现在来看看Python的标识符.引号和注释. 标识符 关于Python的标识符,其实不是与众不同,只是有一定的规则. 标识符是编程时使用的名字.在Python中,标识符有几点 ...