记录编号 89017 评测结果 AAAAAAAAAA
题目名称 动态排名系统 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 2.874 s
提交时间 2014-02-27 18:38:08 内存使用 192.17 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iomanip>
using namespace std;
const int SIZEN=100100,SIZEM=11000;
const int SIZENODE=SIZEN*100;
int N,M;
class FSEG{
public:
	int sum;
	int l,r;
	int lson,rson;
	FSEG(){sum=0;l=r=0;lson=rson=-1;}
};
FSEG ftree[SIZENODE];
int tot=0;
int build(int left,int right){
	if(left>right) return -1;
	int x=tot++;
	ftree[x].l=left,ftree[x].r=right;
	if(right>left){
		int mid=(left+right)>>1;
		ftree[x].lson=build(left,mid);
		ftree[x].rson=build(mid+1,right);
	}
	return x;
}
int change(int p,int x,int t){//在p为根的子树中,节点x加上t
	int root=tot++;
	ftree[root]=ftree[p];//新开一个节点,先复制
	ftree[root].sum+=t;
	if(ftree[root].l==x&&ftree[root].r==x) return root;
	int mid=(ftree[root].l+ftree[root].r)>>1;
	if(x<=mid) ftree[root].lson=change(ftree[root].lson,x,t);//改左节点
	else ftree[root].rson=change(ftree[root].rson,x,t);//改右节点
	return root;
}
class REQUEST{
public:
	char cmd;
	int l,r,k;
};
int cmroot[SIZEN]={0};//外层的树状数组
int A[SIZEN]={0};//初始数据和排序后的所有数
vector<int> avail;
REQUEST req[SIZEM];
int lowbit(int x){
	return x&(-x);
}
void cmchange(int tax,int stx,int t){//树状数组的代表的元素tax中线段树代表的元素stx+=t
	for(int i=tax;i<=avail.size();i+=lowbit(i)) cmroot[i]=change(cmroot[i],stx,t);
}
int lsonsum(vector<int> &ft){//ft中树的左儿子和
	int ans=0;
	for(int i=0;i<ft.size();i++) ans+=ftree[ftree[ft[i]].lson].sum;
	return ans;
}
void goleft(vector<int> &ft){
	for(int i=0;i<ft.size();i++) ft[i]=ftree[ft[i]].lson;
}
void goright(vector<int> &ft){
	for(int i=0;i<ft.size();i++) ft[i]=ftree[ft[i]].rson;
}
int query(vector<int> &lft,vector<int> &rft,int k){//rft-left中所有树之并中的第k个树
	if(ftree[rft[0]].l==ftree[rft[0]].r) return ftree[rft[0]].l;
	int now=lsonsum(rft)-lsonsum(lft);
	if(k<=now){
		goleft(lft);goleft(rft);
		return query(lft,rft,k);
	}
	else{
		goright(lft);goright(rft);
		return query(lft,rft,k-now);
	}
}
int query(int l,int r,int k){
	vector<int> latp,ratp;
	for(int i=l-1;i>0;i-=lowbit(i)) latp.push_back(cmroot[i]);
	for(int i=r;i>0;i-=lowbit(i)) ratp.push_back(cmroot[i]);
	return query(latp,ratp,k);
}
void makecmtree(void){
	cmroot[0]=build(1,avail.size());
	for(int i=1;i<=avail.size();i++) cmroot[i]=cmroot[0];
	for(int i=1;i<=N;i++) cmchange(i,A[i],1);
}
int hash(int x){//找到x在排好序的数组s中是第几个
	return lower_bound(avail.begin(),avail.end(),x)-avail.begin()+1;
}
void work(void){
	for(int i=1;i<=M;i++){
		if(req[i].cmd=='Q') printf("%d\n",avail[query(req[i].l,req[i].r,req[i].k)-1]);
		else if(req[i].cmd=='C'){
			cmchange(req[i].l,A[req[i].l],-1);
			cmchange(req[i].l,req[i].k,1);
			A[req[i].l]=req[i].k;
		}
	}
}
void globalclear(void){
	memset(req,0,sizeof(req));
	memset(A,0,sizeof(A));
	avail.clear();
	memset(cmroot,0,sizeof(cmroot));
	tot=0;
}
void init(void){
	scanf("%d%d",&N,&M);
	vector<int> atp;
	for(int i=1;i<=N;i++) scanf("%d",&A[i]),atp.push_back(A[i]);
	for(int i=1;i<=M;i++){
		cin>>req[i].cmd;
		if(req[i].cmd=='Q')	scanf("%d%d%d",&req[i].l,&req[i].r,&req[i].k);
		else if(req[i].cmd=='C'){
			scanf("%d%d",&req[i].l,&req[i].k);
			atp.push_back(req[i].k);
		}
	}
	sort(atp.begin(),atp.end());
	for(int i=0;i<atp.size();i++) if(!i||atp[i]!=atp[i-1]) avail.push_back(atp[i]);
	for(int i=1;i<=N;i++) A[i]=hash(A[i]);
	for(int i=1;i<=M;i++) if(req[i].cmd=='C') req[i].k=hash(req[i].k);
}
int main(){
	freopen("dynrank.in","r",stdin);
	freopen("dynrank.out","w",stdout);
	int T;scanf("%d",&T);
	while(T--){
		globalclear();
		init();
		makecmtree();
		work();
	}
	return 0;
}