1901: Zju2112 Dynamic Rankings
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 8046 Solved: 3356
[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继续回答上面的问题。
Input
第一行一个数字N,代表测试组数
对于每组数据第一行有两个正整数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
Output
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Sample Input
1
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
6
HINT
m,n≤10000。
题面有问题!!!根本没有什么多组数据
树状数组套主席树,O(nlog^2n)
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar('0'+x%10);}
const int N=100100;
int h[N<<1],num[N<<1],root[N];
inline int hsh(int x,int n)
{
register int l=1,r=n,mid;
while(l<r){mid=(l+r)>>1;h[mid]<x?l=mid+1:r=mid;}
return l;
}
int cnt;
struct president_tree{int sum,ls,rs;}tr[N<<5];
void insert(int &k,int x,int l,int r,int aim,int val)
{
k=++cnt;
tr[k].sum=tr[x].sum+val;tr[k].rs=tr[x].rs;tr[k].ls=tr[x].ls;
if(l==r)return;
int mid=(l+r)>>1;
if(aim<=mid)insert(tr[k].ls,tr[x].ls,l,mid,aim,val);
else insert(tr[k].rs,tr[x].rs,mid+1,r,aim,val);
}
int ltr[N],rtr[N],tot;
inline void query(int x,int y,int rk)
{
register int l=1,r=tot,i,mid,sum;
for(i=y;i;i-=(i&-i))rtr[i]=root[i];
for(i=x;i;i-=(i&-i))ltr[i]=root[i];
while(l<r)
{
sum=0;
for(i=y;i;i-=(i&-i))sum+=tr[tr[rtr[i]].ls].sum;
for(i=x;i;i-=(i&-i))sum-=tr[tr[ltr[i]].ls].sum;
mid=l+r>>1;
if(rk<=sum)
{
for(i=y;i;i-=(i&-i))rtr[i]=tr[rtr[i]].ls;
for(i=x;i;i-=(i&-i))ltr[i]=tr[ltr[i]].ls;
r=mid;
}
else
{
for(i=y;i;i-=(i&-i))rtr[i]=tr[rtr[i]].rs;
for(i=x;i;i-=(i&-i))ltr[i]=tr[ltr[i]].rs;
rk-=sum;l=mid+1;
}
}
print(h[l]);puts("");
}
bool eq[N];
int L[N],R[N],K[N],a[N];
int main()
{
register int i,j,n,m,tmp;
register char opt;
n=read();m=read();tot=n;tmp=1;
for(i=1;i<=n;++i)a[i]=read(),num[i]=a[i];
for(i=1;i<=m;++i)
{
opt=' ';
while(opt^'Q'&&opt^'C')opt=getchar();L[i]=read();R[i]=read();
opt=='Q'?(eq[i]=1,K[i]=read()):(eq[i]=0,num[++tot]=R[i]);
}
sort(num+1,num+1+tot);h[1]=num[1];
for(i=2;i<=tot;++i)if(num[i]!=num[i-1])h[++tmp]=num[i];
tot=tmp;
for(i=1;i<=n;++i)
{
tmp=hsh(a[i],tot);
for(j=i;j<=tot;j+=(j&-j))
insert(root[j],root[j],1,tot,tmp,1);
}
for(i=1;i<=m;++i)
{
if(eq[i])query(L[i]-1,R[i],K[i]);
else
{
tmp=hsh(a[L[i]],tot);//¡£¡£¡£mistook a[i] for a[L[i]] bi¡ª¡ª
for(j=L[i];j<=n;j+=(j&-j))insert(root[j],root[j],1,tot,tmp,-1);
tmp=hsh(R[i],tot);
for(j=L[i];j<=n;j+=(j&-j))insert(root[j],root[j],1,tot,tmp,1);
a[L[i]]=R[i];
}
}
}
/*
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
3
6
*/