终于用主席树过了啊!!!!!
原来是要分两部分搞内存才耗得小啊!!!!!
尼玛ZOJ还不给自动刷新啊,每次交了都要手动search啊有木有!!!!!
分两部分是指原始数列建一个单纯的主席树,有更新的数列建一个用BIT维护的主席树,每次查询的时候在两部分同步二分查询。
主席树唯一的缺点就是耗内存太可怕了,减少消耗的方法以下两点:1、lazy标记,等到真正需要的时候才把这个节点建立起来,个人觉得用指向左右儿子的节点直接来判就好了,不用另外开一个域。2、尽可能多地复用节点,越早建树越好。
刚略有感悟,众犇轻喷即可……
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <string>
#include <bitset>
#include <memory>
#include <complex>
#include <numeric>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <locale.h>
using namespace std;
#pragma pack(4)
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x7f7f7f7f;
#define loop(a,n) \
for(int i=0;n>i;i++) \
cout<<a[i]<<(i!=n-1?' ':'\n')
#define loop2(a,n,m) \
for(int i=0;n>i;i++) \
for(int j=0;m>j;j++) \
cout<<a[i][j]<<(j!=m-1?' ':'\n')
#define at(a,i) ((a)&(1<<(i)))
#define nt(a,i) ((a)^(1<<(i)))
#define set1(a,i) ((a)|(1<<(i)))
#define set0(a,i) ((a)&(~(1<<(i))))
#define gret(a,b) (((a)-(b))>eps)
#define less(a,b) (((b)-(a))>eps)
#define greq(a,b) (((a)-(b))>-eps)
#define leeq(a,b) (((b)-(a))>-eps)
#define equl(a,b) (fabs((a)-(b))<eps)
#define lmax(a,b) ((a)>(b)?(a):(b))
#define lmin(a,b) ((a)<(b)?(a):(b))
#define fmax(a,b) (gret(a,b)?(a):(b))
#define fmin(a,b) (less(a,b)?(a):(b))
const int MAXV = 50002;
const int MAXE = 10002;
class CMT
{
private:
struct node
{
int s;
node *c[2];
int ls(void)
{
return this?c[0]->size():0;
}
int rs(void)
{
return this?c[1]->size():0;
}
int size(void)
{
return this?s:0;
}
}pool[MAXV*40],*a[MAXV],*b[MAXV],*c[33],*d[33];
int use,left,right,amount;
node *malloc(node *root,int w)
{
node *now=&pool[use++];
if(!root)
{
now->s=w;
now->c[0]=NULL;
now->c[1]=NULL;
}
else
{
now->s=w+root->s;
now->c[0]=root->c[0];
now->c[1]=root->c[1];
}
return now;
}
int query(int k,int lc,int ld,int l,int r)
{
if(l==r) return l;
else
{
int sum=0;
for(int i=0;lc>i;i++)
if(c[i]) sum-=c[i]->ls();
for(int i=0;ld>i;i++)
if(d[i]) sum+=d[i]->ls();
if(sum>=k)
{
for(int i=0;lc>i;i++)
if(c[i]) c[i]=c[i]->c[0];
for(int i=0;ld>i;i++)
if(d[i]) d[i]=d[i]->c[0];
return query(k,lc,ld,l,(l+r)/2);
}
else
{
for(int i=0;lc>i;i++)
if(c[i]) c[i]=c[i]->c[1];
for(int i=0;ld>i;i++)
if(d[i]) d[i]=d[i]->c[1];
return query(k-sum,lc,ld,(l+r)/2+1,r);
}
}
}
node *insert(node *root,int x,int w,int l,int r)
{
root=malloc(root,w);
if(l!=r)
{
if(x<=(l+r)/2) root->c[0]=insert(root->c[0],x,w,l,(l+r)/2);
if((l+r)/2<x) root->c[1]=insert(root->c[1],x,w,(l+r)/2+1,r);
}
return root;
}
node *change(node *root,int x,int w,int l,int r)
{
if(!root) root=malloc(NULL,0);
if(l!=r)
{
if(x<=(l+r)/2) root->c[0]=change(root->c[0],x,w,l,(l+r)/2);
if((l+r)/2<x) root->c[1]=change(root->c[1],x,w,(l+r)/2+1,r);
}
return root->s+=w,root;
}
public:
void clear(int n,int l,int r)
{
use=0;
left=l;
right=r;
amount=n;
for(int i=0;n>=i;i++) a[i]=b[i]=NULL;
}
int query(int x,int y,int k)
{
int lc=0,ld=0;
c[lc++]=a[x];
d[ld++]=a[y];
for(int i=x;i>0;i-=(i&-i))
c[lc++]=b[i];
for(int i=y;i>0;i-=(i&-i))
d[ld++]=b[i];
return query(k,lc,ld,left,right);
}
void insert(int i,int x,int w)
{
a[i]=insert(a[i-1],x,w,left,right);
}
void change(int i,int x,int w)
{
while(i<=amount)
{
b[i]=change(b[i],x,w,left,right);
i+=(i&-i);
}
}
}cmt;
struct CMD
{
char o;
int x,y,k;
}cmd[MAXE];
int tcase,n,m,w,a[MAXV],b[MAXV+MAXE];
int rank(int val,int tot)
{
return lower_bound(b,b+tot,val)-b;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("Dynamic Rankings.txt","r",stdin);
#endif
scanf("%d",&tcase);while(tcase--)
{
scanf("%d %d",&n,&m);
int cnt=0;
for(int i=0;n>i;i++)
{
scanf("%d",&a[i]);
b[cnt++]=a[i];
}
for(int i=0;m>i;i++)
{
getchar();
scanf("%c",&cmd[i].o);
if(cmd[i].o=='Q')
{
scanf("%d %d %d",&cmd[i].x,&cmd[i].y,&cmd[i].k);
}
else if(cmd[i].o=='C')
{
scanf("%d %d",&cmd[i].x,&cmd[i].y);
b[cnt++]=cmd[i].y;
}
}
int tot=1;
sort(b,b+cnt);
for(int i=1;cnt>i;i++)
{
if(b[i]!=b[i-1]) b[tot++]=b[i];
}
cmt.clear(n,0,tot-1);
for(int i=0;n>i;i++)
{
cmt.insert(i+1,rank(a[i],tot),+1);
}
for(int i=0;m>i;i++)
{
if(cmd[i].o=='Q')
{
printf("%d\n",b[cmt.query(cmd[i].x-1,cmd[i].y,cmd[i].k)]);
}
else if(cmd[i].o=='C')
{
cmt.change(cmd[i].x,rank(a[cmd[i].x-1],tot),-1);
a[cmd[i].x-1]=cmd[i].y;
cmt.change(cmd[i].x,rank(a[cmd[i].x-1],tot),+1);
}
}
}
return 0;
}