题目链接
https://www.luogu.com.cn/problem/P1110
思路
此题不需要平衡树,只需要一个邻接表和两个
m
u
l
t
i
s
e
t
multiset
multiset即可。
将原序列中的每个元素,分别映射到邻接表中的每一个表头的第一个节点上。
样例中执行完两个
i
n
s
e
r
t
insert
insert操作之后的邻接表如图所示。
我们可以使用两个
m
u
l
t
i
s
e
t
<
i
n
t
>
multiset<int>
multiset<int>
s
t
1
st1
st1和
s
t
st
st。
s
t
1
st1
st1用来存储相邻两个数的差值的绝对值,
s
t
st
st用来存储数组中的所有元素。
如上图所示,对于新添加的元素
6
6
6,我们从
s
t
1
st1
st1中删除原本相邻的
9
9
9和
1
1
1的差值,并插入新产生的差值:
9
9
9和
6
6
6的,
6
6
6和
1
1
1的。这样,我们便可以动态地维护MIN_GAP的值。
将新添加的元素
6
6
6插入到
s
t
st
st中,并直接计算该元素在
s
t
st
st中前后两个元素的差值,动态更新MIN_SORT_GAP的值。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, m;
vector<int>a[N];
void solve()
{
cin >> n >> m;
for (int i = 1, x; i <= n; i++)
{
cin >> x;
a[i].push_back(x);
}
string s;
int i, k, ans = inf;
multiset<int>st1;//存储相邻两个数的差值的绝对值
for (int i = 2; i <= n; i++)
{
st1.insert(abs(a[i][0] - a[i - 1][0]));
}
multiset<int>st;
for (int i = 1; i <= n; i++)
{
st.insert(a[i][0]);
}
for (set<int>::iterator it = st.begin(); it != st.end(); it++)
{
if (it == st.begin()) continue;
ans = min(ans, abs((*prev(it)) - (*it)));
}
st.insert(-1);//废掉st.begin()
while (m--)
{
cin >> s;
if (s == "INSERT")
{
cin >> i >> k;
//更新st1
if (i < n)
{
int op = abs(a[i][a[i].size() - 1] - a[i + 1][0]);
st1.erase(st1.find(op));
}
st1.insert(abs(a[i][a[i].size() - 1] - k));
a[i].push_back(k);
if (i < n)
st1.insert(abs(a[i][a[i].size() - 1] - a[i + 1][0]));
//更新ans
st.insert(k);
set<int>::iterator it = st.find(k);
if (prev(it) != st.begin())
{
ans = min(ans, abs((*it) - (*prev(it))));
}
it++;
if (it != st.end())
{
ans = min(ans, abs((*it) - (*prev(it))));
}
}
if (s == "MIN_GAP")
{
cout << *st1.begin() << endl;
}
if (s == "MIN_SORT_GAP")
{
cout << ans << endl;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}