题目描述
有一个包含n个元素的数组,要求实现以下操作:
DELETE k :删除位置k上的数。右边的数往左移一个位置。
QUERY i j :查询位置i~j上所有数的最小值和最大值。
例如有10个元素:
QUERY 2 8的结果为2 9。依次执行DELETE 3和DELETE 6(注意这时删除的是原始数组的元素7)后数组变为:
QUERY 2 8的结果为1 7。
题目大意
删数,求区间最大最小值。
数据范围
1≤n, m≤10^6 数字绝对值小于10^9
样例输入
10 4
1 5 2 6 7 4 9 3 1 5
2 2 8
1 3
1 6
2 2 8
样例输出
2 9
1 7
解题思路
Splay
代码
注意常数巨大,scanf都会超时一组。
#include <bits/stdc++.h>
#define Maxn 1000005
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
int a[Maxn],n;
struct splay{
int f[Maxn],son[Maxn][2],size[Maxn],vl[Maxn],Max[Maxn],Min[Maxn],root;
void PushUp(int x){
if(!x)return;
size[x]=size[son[x][0]]+size[son[x][1]]+1;
Max[x]=max(max(Max[son[x][0]],Max[son[x][1]]),(x==1||x==n+2?-1<<30:vl[x]));
Min[x]=min(min(Min[son[x][0]],Min[son[x][1]]),(x==1||x==n+2?1<<30:vl[x]));
}
void Rotate(int x){
int fa=f[x],gr=f[fa],s=son[fa][1]==x,sn=son[x][!s];
son[f[x]=gr][son[gr][1]==fa]=x;
son[f[sn]=fa][s]=sn;
son[f[fa]=x][!s]=fa;
PushUp(sn);
PushUp(fa);
PushUp(x);
}
void Splay(int x,int goal){
if(x==goal)return;
while(f[x]!=goal){
if(f[f[x]]!=goal&&(son[f[f[x]]][1]==f[x])==(son[f[x]][1]==x))Rotate(f[x]);
Rotate(x);
}
if(!goal)root=x;
}
int Select(int pos){
if(!pos)return 0;
int p=root;
while(size[son[p][0]]+1!=pos){
if(pos<=size[son[p][0]])p=son[p][0];
else pos-=size[son[p][0]]+1,p=son[p][1];
}
return p;
}
void Delete(int pos){
int u=Select(pos),v=Select(pos+2);
Splay(u,0);
Splay(v,u);
size[son[v][0]]=0;
f[son[v][0]]=0;
son[v][0]=0;
PushUp(v);
PushUp(u);
}
void Build(int L,int r,int fa){
if(L>r)return;
int mid=(L+r)/2;
if(L==r){
Min[mid]=Max[mid]=vl[mid]=a[mid-1];
size[mid]=1;
}else Build(L,mid-1,mid),Build(mid+1,r,mid);
vl[mid]=a[mid-1];
f[mid]=fa;
PushUp(mid);
son[fa][mid>=fa]=mid;
}
void Solve(int L,int r){
int u=Select(L),v=Select(r+2);
Splay(u,0);
Splay(v,u);
cout<<Min[son[v][0]]<<" "<<Max[son[v][0]]<<"\n";
}
void Init(int n){
Min[n+1]=Min[0]=1<<30;
Max[n+1]=Max[0]=-1<<30;
Build(1,n+2,0);
root=n+3>>1;
}
}Solver;
int main(){
n=Getint();
int m=Getint();
for(int i=1;i<=n;i++)a[i]=Getint();
Solver.Init(n);
while(m--){
int op=Getint();
if(op==1)Solver.Delete(Getint());
else{
int L=Getint(),r=Getint();
Solver.Solve(L,r);
}
}
return 0;
}
附我们学校OJ里超时的result