1901: Zju2112 Dynamic Rankings
Time Limit: 10 Sec
Memory Limit: 162 MB
Submit: 1846
Solved: 763
[ 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,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t 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。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
HINT
20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。
Source
[ Submit][ Status][ Discuss]
主席树2阶应用
首先建一棵树状数组,每个数组里套值域线段树
显然开不下——函数式
qur时暴力把LogN棵树的所需结点相加
O(nlog^2n)
然后就A了……
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define MAXN (10000+10)
#define MAXM (10000+10)
#define MAXAi (1000000000+10)
#define MINAi (0)
int n,m,a[MAXN];
struct node
{
int ch[2],c,fa;
node():c(0),fa(0){ch[0]=ch[1]=0;}
}q[MAXN*4*100];
int root[MAXN]={0},tot=0;
void insert(int &x,int l,int r,int c,int d)
{
if (!x) x=++tot;
q[x].c+=d;
int m=l+r>>1;
if (l==r) return;
if (c<=m) insert(q[x].ch[0],l,m,c,d),q[q[x].ch[0]].fa=x;
else insert(q[x].ch[1],m+1,r,c,d),q[q[x].ch[1]].fa=x;
}
void update(int x,int c,int d)
{
for(int i=x;i<=n;i+=i&(-i)) insert(root[i],MINAi,MAXAi,c,d);
}
int ans[MAXN],ans_siz=0;
void qur(int x)
{
for(int i=x;i;i-=i&(-i)) ans[++ans_siz]=root[i];
}
void turn(bool c)
{
For(i,ans_siz) ans[i]=q[ans[i]].ch[c];
}
int main()
{
// freopen("bzoj1901.in","r",stdin);
// freopen(".out","w",stdout);
scanf("%d%d",&n,&m);
For(i,n) scanf("%d",&a[i]),update(i,a[i],1);
while (m--)
{
char c[2];
scanf("%s",c);
switch(c[0])
{
case 'C':
{
int i,c;
scanf("%d%d",&i,&c);
update(i,a[i],-1);
update(i,a[i]=c,1);
break;
}
default:
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
ans_siz=0;
qur(r);int ad_end=ans_siz;qur(l-1);
l=MINAi,r=MAXAi;
while (l<r)
{
int m=l+r>>1,s=0;
For(i,ad_end) s+=q[q[ans[i]].ch[0]].c;
Fork(i,ad_end+1,ans_siz) s-=q[q[ans[i]].ch[0]].c;
if (k<=s) turn(0),r=m;else turn(1),l=m+1,k-=s;
}
cout<<l<<endl;
}
}
}
return 0;
}