表示主席樹+樹狀數組懶得打了,學了樹套樹水過。。。
線段樹套平衡樹
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=12005;
const int inf=0x3f3f3f3f;
int n,m,tmp;
int c[N];
inline int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
int tot,size[N*18],fa[N*18],ch[N*18][2],cnt[N*18],val[N*18];
struct sigment
{
int l,r;
int rt;
void up(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (z)
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
void splay(int x,int k)
{
int y,z;
while (fa[x]!=k)
{
y=fa[x],z=fa[y];
if (z!=k)
if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
rot(x);
}
if (k==0) rt=x;
up(x);
}
void insert(int x)
{
if (rt==0)
{
rt=++tot;size[rt]=cnt[rt]=1;val[rt]=x;return ;
}
int k=rt;
while (true)
{
size[k]++;
if (val[k]==x) {cnt[k]++;return;}
int y=ch[k][x>val[k]];
if (!y)
{
++tot;
fa[tot]=k;val[tot]=x;cnt[tot]=size[tot]=1;ch[k][x>val[k]]=tot;
k=tot;break;
}
k=y;
}
splay(k,0);
}
int find(int i,int x)
{
if (val[i]==x) return i;
if (val[i]>x) return find(ch[i][0],x);
else return find(ch[i][1],x);
}
int small_num(int i,int x)
{
if (i==0) return 0;
if (val[i]==x) return size[ch[i][0]];
if (val[i]>x) return small_num(ch[i][0],x);
return size[ch[i][0]]+cnt[i]+small_num(ch[i][1],x);
}
void del(int x)
{
int k=find(rt,x);
splay(k,0);
if (cnt[k]>1){cnt[k]--;size[k]--;return ;}
if (ch[k][0]==0&&ch[k][1]==0) {rt=0;return ;}
if (ch[k][0]==0) {rt=ch[k][1];fa[rt]=0;return ;}
if (ch[k][1]==0) {rt=ch[k][0];fa[rt]=0;return ;}
int y=ch[k][0];
while (ch[y][1]) y=ch[y][1];
splay(y,k);
rt=y;fa[rt]=0;fa[ch[k][1]]=y;ch[y][1]=ch[k][1];
up(y);
}
}a[N*4];
void build(int i,int l,int r)
{
a[i].l=l;a[i].r=r;
for (int j=l;j<=r;j++) a[i].insert(c[j]);
if (l==r) return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void updata(int i,int l,int k)
{
a[i].del(c[l]);
a[i].insert(k);
if (a[i].l==a[i].r) return ;
int mid=(a[i].l+a[i].r)>>1;
if (mid>=l) updata(i<<1,l,k);
else updata(i<<1|1,l,k);
}
void find_rank(int i,int l,int r,int x)
{
if (a[i].l==l&&a[i].r==r)
{
tmp+=a[i].small_num(a[i].rt,x);
return;
}
int mid=(a[i].l+a[i].r)>>1;
if (mid>=r) find_rank(i<<1,l,r,x);
else if (mid<l) find_rank(i<<1|1,l,r,x);
else find_rank(i<<1,l,mid,x),find_rank(i<<1|1,mid+1,r,x);
}
void rank_k(int l,int r,int x)
{
int ml=0,mr=1e9,mid,ans=0;
while(ml<=mr)
{
mid=(ml+mr)>>1;
tmp=0;find_rank(1,l,r,mid);
if (tmp<=x-1){ans=mid;ml=mid+1;}
else mr=mid-1;
}
printf("%d\n",ans);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&c[i]);
build(1,1,n);
int l,r,x;
char ch[5];
while (m--)
{
scanf("%s",ch);
switch(ch[0])
{
case 'Q':scanf("%d%d%d",&l,&r,&x);rank_k(l,r,x);break;
case 'C':scanf("%d%d",&l,&x);updata(1,l,x);c[l]=x;break;
}
}
return 0;
}
總結
1.果然這個數據範圍不寫讀入優化是不行的。。