T了5个点的splay
好吧,突然发现方法好像错了,不过学了一个splay_tree结构体的定义
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<set>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int N=1500010;
const int inf=0x3f3f3f3f;
struct splay_tree
{
int fa[N],ch[N][2],v[N],rt,tot;
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;
}
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;
}
void insert(int val)
{
if (rt==0) {rt=++tot;v[tot]=val;return ;}
int y,i=rt;
while (i)
{
y=ch[i][v[i]<val];
if (!y)
{
v[++tot]=val;
ch[i][v[i]<val]=tot;
fa[tot]=i;
i=tot;
break;
}
i=y;
}
splay(i,0);
}
int find(int i,int val)
{
if (i==0) return 0;
if (v[i]==val) return i;
if (v[i]>val) return find(ch[i][0],val);
else return find(ch[i][1],val);
}
void del(int val)
{
int k=find(rt,val);
if (k==0) return ;
splay(k,0);
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[y]=0;ch[y][1]=ch[k][1];fa[ch[k][1]]=y;
}
int pre(int k)
{
int y=ch[k][0];
while (ch[y][1]) y=ch[y][1];
return v[y];
}
int next(int k)
{
int y=ch[k][1];
while (ch[y][0]) y=ch[y][0];
return v[y];
}
int min()
{
int y=rt;
while (ch[y][0]) y=ch[y][0];
splay(y,0);
return v[y];
}
}s1,s2;
int n,m,lx[N],rx[N],ans;
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;
}
void inin(int d)
{
s2.insert(d);
ans=min(ans,s2.next(s2.rt)-d);
ans=min(ans,d-s2.pre(s2.rt));
}
void in()
{
int pos=read(),d=read();
if (pos<n) s1.del(abs(rx[pos]-lx[pos+1]));
s1.insert(abs(d-rx[pos]));
if (pos<n) s1.insert(abs(d-lx[pos+1]));
rx[pos]=d;
inin(d);
}
int main()
{
n=read();m=read();
for (int i=1;i<=n;i++) rx[i]=lx[i]=read();
for (int i=1;i<n;i++) s1.insert(abs(lx[i+1]-lx[i]));
s2.insert(inf);s2.insert(-inf);ans=inf;
for (int i=1;i<=n;i++) inin(lx[i]);
char c[20];
while (m--)
{
scanf("%s",c);
if (c[0]=='I') in();
if (c[4]=='G') printf("%d\n",s1.min());
if (c[4]=='S') printf("%d\n",ans);
}
return 0;
}
决定用set水过把,
吐槽一下:小Q竟然不会stl。。。。
不过stl能过,为什么同样思路的splay就过不了呢??呜呜呜~~,该不会是我写炸了吧
#include<cstdio>
#include<set>
#include<algorithm>
#include<iostream>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int inf=0x3f3f3f3f;
multiset<int> num,diff;//一个存差值维护相邻差值,一个存总的数的集合
multiset<int>::iterator it,last;
int n,m,lx[500000],rx[500000],ans;
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&lx[i]);
rx[i]=lx[i];
num.insert(lx[i]);
}
for (int i=2;i<=n;i++) diff.insert(abs(lx[i]-lx[i-1]));
ans=inf;
num.insert(inf);num.insert(-inf);
for (it=num.begin();it!=num.end();it++)
{
if (it!=num.begin())
ans=min(ans,*it-*last);//从左向右遍历,取集合最小差值
last=it;
}
char ch[20];
int pos,d;
while (m--)
{
scanf("%s",ch);
if (ch[0]=='I')
{
scanf("%d%d",&pos,&d);
it=diff.find(abs(rx[pos]-lx[pos+1]));
diff.erase(it);//multiset,只能删除一个,就是应该删迭代器
diff.insert(abs(rx[pos]-d));
diff.insert(abs(d-lx[pos+1]));
rx[pos]=d;
it=num.insert(d);//set的insert函数是有返回值的返回所处的迭代器
ans=min(ans,d-*(--it));it++;it++;//这里要用--it,否则会错,++ -- 两个都是log的复杂度,就是前驱和后继
ans=min(ans,*it-d);
}
else
if(ch[4]=='G') printf("%d\n",*diff.begin());//begin()最小值
else printf("%d\n",ans);
}
return 0;
}