背景:
调了
3
3
3天,查了一下
s
e
t
set
set中的
l
o
w
e
r
_
b
o
u
n
d
lower\_bound
lower_bound的时间复杂度,发现了…
然后跑到了
r
a
n
k
10
rank10
rank10。
题目传送门:
https://www.luogu.org/problemnew/show/P1110
题意:
刚开始有
n
n
n个数,共
n
n
n块。
三个操作:
1.
1.
1.在第
n
n
n个块的最后一个位置加上一个数;
2.
2.
2.查找相邻两个数的差值的最小值;
3.
3.
3.查找所有数中的差值的最小值。
思路:
发现没有修改操作。
那就考虑
S
T
L
STL
STL吧。
考虑操作
2
2
2先。
最小值的维护显然想到了堆。不妨开一个堆来记录相邻两个块的差值。然后对于每一个块的贡献是单调不递增的,直接用一个数组维护。
在加入操作时,不妨给要删除的堆中的元素打上删除标记,当它为堆顶时,直接删除。然后更新数组和堆即可。
在考虑操作
3
3
3。
直接用
s
e
t
set
set维护数,没有什么难度,贡献也是单调不递减的。
调了
3
3
3天发现:
S
T
L
STL
STL中的
l
o
w
e
r
_
b
o
u
n
d
lower\_bound
lower_bound在
s
e
t
set
set中使用时间复杂度是
Θ
(
n
l
o
g
n
)
\Theta(nlogn)
Θ(nlogn)的,要用
s
e
t
set
set中的
l
o
w
e
r
_
b
o
u
n
d
lower\_bound
lower_bound使得时间复杂度为
Θ
(
l
o
g
n
)
\Theta(logn)
Θ(logn)。
坑死,但也学到了…
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<vector>
#include<algorithm>
#define ID set<int>::iterator
using namespace std;
struct node
{
int id;
int x;
bool friend operator <(const node x,const node y)
{
return x.x>y.x;
}
};
priority_queue<node> f;
set<int> p;
int n,m,ans=2147483647,p_min=2147483647;
int front[500010],last[500010],will[500010];
char s[20];
int read()
{
int x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
return x*f;
}
void work1(int y)
{
if(!p_min||*p.lower_bound(y)==y) {p_min=0;return;}
p.insert(y);
ID now=p.lower_bound(y),i,j;
if(now!=p.begin())
{
i=--now;
now++;
p_min=min(p_min,abs(y-*i));
}
if(now!=p.end())
{
j=++now;
if(j==p.end()) return;
now--;
p_min=min(p_min,abs(*j-y));
}
}
void work2(int x,int y)
{
last[x]=y;
will[x]=abs(last[x]-front[x+1]);
while(!f.empty()&&f.top().x!=will[f.top().id])
f.pop();
f.push((node){x,will[x]});
}
int main()
{
int x,y=2147483647;
n=read(),m=read();
memset(front,63,sizeof(front));
memset(last,63,sizeof(last));
p.insert(-1000000000),p.insert(1000000000);
for(int i=1;i<=n;i++)
{
x=read();
if(p_min||*p.lower_bound(x)!=x) p.insert(x); else p_min=0;
will[i-1]=abs(x-y);
f.push((node){i-1,will[i-1]});
front[i]=last[i]=x;
y=x;
}
if(p_min)
for(ID i=p.begin();i!=p.end();i++)
{
ID j=++i;
if(j==p.end()) break;
i--;
p_min=min(p_min,abs(*i-*j));
}
for(int i=1;i<=m;i++)
{
scanf("%s",s+1);
if(s[1]=='I')
{
x=read(),y=read();
work1(y);
ans=min(ans,abs(y-last[x]));
if(y!=last[x]) work2(x,y);
}
else if(s[5]=='G')
{
while(!f.empty()&&f.top().x!=will[f.top().id])
f.pop();
printf("%d\n",min(ans,f.top().x));
}
else
{
printf("%d\n",p_min);
}
}
}