我又来填坑了哈哈哈!!!!
Description:
有一个初始序列,长度为 N(N<=50000)
两种操作,操作个数为 M(M<=10000) :
1.询问一个区间里第k小的数;
2.修改数列中一个数的值。
Solution:
首先如果不带修改的话,就是直接上主席树就行了,主席树做区间第 k 大在这里就不再赘述了。
然后就愉快的
AC
了。
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int N;
int M;
int T;
struct tree_
{
int son[2];
int sum;
}tree[2000010]={{{0},0}};
struct cz_
{
char ch;
int a1,a2,a3;
}cz[10010]={{'\0',0,0,0}};
int tp=0;
int root1[50010]={0},root2[50010]={0};
int a[50010]={0};
int L[50010]={0},R[50010]={0};
int Lp=0,Rp=0;
int val[60010]={0},vp=0;
void read_char(char &ch)
{
ch=getchar();
for(;ch==' ' || ch=='\n' || ch=='\r' || ch=='\0';ch=getchar());
return;
}
int lowbit(int x)
{return x&(-x);}
int check(int k)
{
for(int l=1,r=vp;l<=r;)
{
int mid=(l+r)>>1;
if(val[mid]==k)
return mid;
if(val[mid]<k)
l=mid+1;
else r=mid-1;
}
return 0;
}
void Pre_(int l,int r,int k)
{
if(l==r) return;
int mid=(l+r)>>1;
tree[k].son[0]=++tp;
Pre_(l,mid,tree[k].son[0]);
tree[k].son[1]=++tp;
Pre_(mid+1,r,tree[k].son[1]);
return;
}
void Clear(int x,int *G,int &Gp)
{
Gp=0;
for(;x>=1;x-=lowbit(x))
G[++Gp]=root2[x];
return;
}
void Change(int New,int Old,int l,int r,int o,int add)
{
tree[New]=tree[Old];tree[New].sum+=add;
if(l==r) return;
int mid=(l+r)>>1;
int gg=(o>mid);
tree[New].son[gg]=++tp;
if(gg==0) Change(tree[New].son[gg],tree[Old].son[gg],l,mid,o,add);
else Change(tree[New].son[gg],tree[Old].son[gg],mid+1,r,o,add);
return;
}
int Find(int cnt1,int cnt2,int k,int l,int r)
{
if(l==r) return l;
int mid=(l+r)>>1;
int sum=tree[tree[cnt2].son[0]].sum-tree[tree[cnt1].son[0]].sum;
for(int i=1;i<=Rp;i++)
sum+=tree[tree[R[i]].son[0]].sum;
for(int i=1;i<=Lp;i++)
sum-=tree[tree[L[i]].son[0]].sum;
int gg=0;
if(sum<k)
gg=1,k-=sum;
for(int i=1;i<=Rp;i++)
R[i]=tree[R[i]].son[gg];
for(int i=1;i<=Lp;i++)
L[i]=tree[L[i]].son[gg];
if(gg==0) return Find(tree[cnt1].son[gg],tree[cnt2].son[gg],k,l,mid);
return Find(tree[cnt1].son[gg],tree[cnt2].son[gg],k,mid+1,r);
}
int main()
{
scanf("%d",&T);
for(;T>0;T--)
{
tp=vp=0;
scanf("%d%d",&N,&M);
root1[0]=++tp;
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
val[++vp]=a[i];
}
for(int i=1;i<=M;i++)
{
read_char(cz[i].ch);
if(cz[i].ch=='Q') scanf("%d%d%d",&cz[i].a1,&cz[i].a2,&cz[i].a3);
else scanf("%d%d",&cz[i].a1,&cz[i].a2),val[++vp]=cz[i].a2;
}
sort(val+1,val+vp+1);
int help=1;
for(int i=2;i<=vp;i++)
if(val[i]!=val[i-1])
val[++help]=val[i];
vp=help;
Pre_(1,vp,root1[0]);
for(int i=1;i<=N;i++)
{
root1[i]=++tp;
int place=check(a[i]);
Change(root1[i],root1[i-1],1,vp,place,1);
}
root2[0]=++tp;
Pre_(1,vp,root2[0]);
for(int i=1;i<=N;i++)
root2[i]=root2[0];
for(int i=1;i<=M;i++)
{
if(cz[i].ch=='Q')
{
int l,r,k;
l=cz[i].a1,r=cz[i].a2,k=cz[i].a3;
Clear(r,R,Rp);Clear(l-1,L,Lp);
int tmp=Find(root1[l-1],root1[r],k,1,vp);
printf("%d\n",val[tmp]);
}
else
{
int p,q,place=check(a[cz[i].a1]);
p=cz[i].a1,q=check(cz[i].a2);
for(int j=p;j<=N;j+=lowbit(j))
{
int t=++tp;
Change(t,root2[j],1,vp,place,-1);
root2[j]=t;t=++tp;
Change(t,root2[j],1,vp,q,1);
root2[j]=t;
}
a[cz[i].a1]=cz[i].a2;
}
}
memset(tree,0,sizeof(struct tree_)*(tp+10));
}
return 0;
}