传送门
平衡树裸题,用
m
u
l
t
i
s
e
t
multiset
multiset和堆好像也能做
就是用两个平衡树分别维护相邻两数差和每个数的数值,然后求相邻两数差最小值就是求第一个平衡树里的最小值,求任意两数差最小值就用第二个平衡树根查一下前驱后继这样维护一下最小值就好了
但写平衡树的话就是一个卡常神题了···
之前一直
t
t
t掉一个点,改了改
i
n
s
e
r
t
insert
insert就过了
(吸氧吸氧)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000005
#define inf 0x3f3f3f3f
using namespace std;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
inline int abs(int x){return x>=0?x:-x;}
inline int min(int x,int y){return x<y?x:y;}
char s[20];
int n,m,ans,a[N],b[N];
struct Tree{
int root,sz,ch[N][2],cnt[N],siz[N],f[N],key[N];
Tree(){
root=sz=0; memset(ch,0,sizeof ch);
memset(siz,0,sizeof siz); memset(cnt,0,sizeof cnt);
memset(f,0,sizeof f); memset(key,0,sizeof key);
}
int get(int x){return ch[f[x]][1]==x;}
void clear(int x){
ch[x][0]=ch[x][1]=cnt[x]=siz[x]=f[x]=key[x]=0; return;
}
void pushup(int x){
if(x){
siz[x]=cnt[x];
if(ch[x][0]) siz[x]+=siz[ch[x][0]];
if(ch[x][1]) siz[x]+=siz[ch[x][1]];
}
}
void rotate(int x){
int old=f[x],oldf=f[old],wh=get(x);
f[ch[x][wh^1]]=old; ch[old][wh]=ch[x][wh^1];
f[old]=x; ch[x][wh^1]=old; f[x]=oldf;
if(oldf) ch[oldf][ch[oldf][1]==old]=x;
pushup(old); pushup(x);
}
void splay(int x){
for(int fa;(fa=f[x]);rotate(x))
if(f[fa])
rotate(get(x)==get(fa)?fa:x);
root=x;
}
void insert(int x){
if(root==0){
++sz; ch[sz][0]=ch[sz][1]=f[sz]=0;root=sz;
siz[sz]=cnt[sz]=1;key[sz]=x; return;
}
int now=root,fa=0;
// while(1){
// if(x==key[now]){
// ++cnt[now]; pushup(now); pushup(fa); splay(now);
// break;
// }
// fa=now;
// now=ch[now][key[now]<x];
// if(now==0){
// ++sz; ch[sz][0]=ch[sz][1]=0; f[sz]=fa;
// siz[sz]=cnt[sz]=1; ch[fa][key[fa]<x]=sz;
// key[sz]=x; pushup(fa); splay(sz);
// break;
// }
// }
while(now && key[now]!=x){
fa=now; now=ch[now][key[now]<x];
}
if(now) ++cnt[now];
else{
now=++sz; ch[sz][0]=ch[sz][1]=0; f[sz]=fa;
siz[sz]=cnt[sz]=1; ch[fa][key[fa]<x]=sz;
key[sz]=x; pushup(fa);
}
splay(now); return;
}
int pre(){
int now=ch[root][0];
while(ch[now][1]) now=ch[now][1];
return now;
}
int nxt(){
int now=ch[root][1];
while(ch[now][0]) now=ch[now][0];
return now;
}
int find(int x){
int now=root,res=0;
while(1){
if(x<key[now]) now=ch[now][0];
else{
res+=ch[now][0]?siz[ch[now][0]]:0;
if(x==key[now]){
splay(now); return res+1;
}
res+=cnt[now];
now=ch[now][1];
}
}
}
void del(int x){
int useless=find(x);
if(cnt[root]>1) {cnt[root]--;pushup(root);return;}
if(!ch[root][0] && !ch[root][1]) {clear(root);root=0;return;}
if(!ch[root][0]){
int oldrt=root; root=ch[root][1]; f[root]=0;
clear(oldrt); return;
}
else if(!ch[root][1]){
int oldrt=root; root=ch[root][0]; f[root]=0;
clear(oldrt); return;
}
int lf=pre(),oldrt=root;
splay(lf);
ch[root][1]=ch[oldrt][1]; f[ch[oldrt][1]]=root;
clear(oldrt); pushup(root); return;
}
int findx(int x){
int now=root,tmp;
while(1){
if(ch[now][0] && x<=siz[ch[now][0]])
now=ch[now][0];
else{
tmp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
if(x<=tmp) return key[now];
x-=tmp; now=ch[now][1];
}
}
}
void getans(){
if(cnt[root]>1) {ans=0;return;}
int u=pre(),v=nxt();
if(u) ans=min(ans,key[root]-key[u]);
if(v) ans=min(ans,key[v]-key[root]);
return;
}
}A,B;
int main(){
// freopen("in.txt","r",stdin);
// freopen("out2.txt","w",stdout);
n=rd(); m=rd();
for(int i=1;i<=n;i++) a[i]=b[i]=rd();
a[n+1]=b[n+1]=ans=inf; B.insert(a[1]);
for(int i=2;i<=n;i++){
A.insert(abs(a[i]-a[i-1]));
B.insert(a[i]); B.getans();
}
int x,y;
while(m--){
scanf("%s",s);
if(s[0]=='I'){
x=rd(),y=rd();
B.insert(y); B.getans();
A.del(abs(a[x+1]-b[x]));
A.insert(abs(y-b[x])); A.insert(abs(a[x+1]-y));
b[x]=y;
}
else if(s[4]=='G'){
printf("%d\n",A.findx(1));
}
else{
printf("%d\n",ans);
}
}
return 0;
}
话说 n o i p noip noip的游记好像一直都没有写···算了出了分再写吧 Q A Q QAQ QAQ