标签:
在线维护一个序列,需要兹瓷插入、修改、求区间K小值。
开一颗权值线段树。
对于区间[l,r]对应的结点上保存一颗spaly,spaly中的结点权值均在[l,r],按照位置从小到大。
要维护一个结点的位置号。
插入操作,往下走然后插入到spaly中,并打区间加标记来维护位置号。
修改操作,相当于一次删除一次插入。
询问操作,利用线段树特性查找即可。
嘴巴我会,你要我打……还没准备好。
分块。
设c为我们定的块大小。
每一块维护原数组、排序后数组、以及块大小。
然后插入操作时,如果插入的那个块大小刚好为2*c就裂成两个块。
这个打法我是参考swm_sxt的题解
因为是分块所以一切暴力搞就好。
查询自然是最经典的二分,然后转化为判定性问题。块内可以直接二分。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=70000+10,maxc=600+10,maxd=10000+10;
int next[maxd],size[maxd];
int a[maxd][maxc*2],b[maxd][maxc*2];
int i,j,k,l,t,n,m,c,tot,ans;
bool czy;
char ch;
inline char get(){
char ch=getchar();
while (ch!=‘Q‘&&ch!=‘M‘&&ch!=‘I‘) ch=getchar();
return ch;
}
inline void rebuild(int x){
int i;
fo(i,1,size[x]) b[x][i]=a[x][i];
sort(b[x]+1,b[x]+size[x]+1);
}
inline int binary(int x,int y){
int l=0,r=size[x],mid;
while (l<r){
mid=(l+r+1)/2;
if (b[x][mid]<y) l=mid;else r=mid-1;
}
return l;
}
inline int query(int l,int r,int k){
int ll=1,rr=1,i,j,t;
while (size[ll]<l){
l-=size[ll];
ll=next[ll];
}
while (size[rr]<r){
r-=size[rr];
rr=next[rr];
}
int lll=0,rrr=70000,mid;
while (lll<rrr){
mid=(lll+rrr+1)/2;
t=0;
if (ll==rr){
fo(i,l,r)
if (a[ll][i]<mid) t++;
}
else{
fo(i,l,size[ll])
if (a[ll][i]<mid) t++;
fo(i,1,r)
if (a[rr][i]<mid) t++;
j=next[ll];
while (j!=rr){
t+=binary(j,mid);
j=next[j];
}
}
if (t<=k-1) lll=mid;else rrr=mid-1;
}
return lll;
}
inline void change(int x,int y){
int i,j=1,k;
while (size[j]<x){
x-=size[j];
j=next[j];
}
fo(i,1,size[j])
if (b[j][i]==a[j][x]) break;
b[j][i]=a[j][x]=y;
k=i;
while (k>1&&b[j][k]<b[j][k-1]){
swap(b[j][k],b[j][k-1]);
k--;
}
while (k<size[j]&&b[j][k]>b[j][k+1]){
swap(b[j][k],b[j][k+1]);
k++;
}
}
inline void insert(int x,int y){
int i,j=1,k;
while (size[j]<x){
x-=size[j];
j=next[j];
}
fd(i,size[j],x+1) a[j][i+1]=a[j][i];
size[j]++;
a[j][x+1]=y;
b[j][size[j]]=y;
if (size[j]==2*c){
next[++tot]=next[j];
next[j]=tot;
fo(i,1,c) a[tot][i]=a[j][i+c];
size[j]=size[tot]=c;
rebuild(j);rebuild(tot);
}
else{
k=size[j];
while (k>1&&b[j][k]<b[j][k-1]){
swap(b[j][k],b[j][k-1]);
k--;
}
}
}
inline int read(){
int x=0;
char ch=getchar();
while (ch<‘0‘||ch>‘9‘) ch=getchar();
while (ch>=‘0‘&&ch<=‘9‘){
x=x*10+ch-‘0‘;
ch=getchar();
}
return x;
}
int main(){
freopen("3065.in","r",stdin);freopen("3065.out","w",stdout);
czy=1;
c=600;
n=read();
fo(i,1,n){
t=read();
a[(i-1)/c+1][(i-1)%c+1]=t;
size[(i-1)/c+1]++;
}
tot=(n-1)/c+1;
fo(i,1,tot){
rebuild(i);
if (i<tot) next[i]=i+1;
}
m=read();
while (m--){
ch=get();
if (ch==‘Q‘){
j=read();k=read();l=read();
if (czy) j^=ans,k^=ans,l^=ans;
ans=query(j,k,l);
printf("%d\n",ans);
}
else if (ch==‘M‘){
j=read();k=read();
if (czy) j^=ans,k^=ans;
change(j,k);
}
else{
j=read();k=read();
if (czy) j^=ans,k^=ans;
insert(j-1,k);
}
}
fclose(stdin);fclose(stdout);
}
标签:
原文地址:http://blog.csdn.net/werkeytom_ftd/article/details/51335048