题目链接
https://codeforces.com/problemset/problem/1922/D
思路
假设在某一轮,元素 a x a_{x} ax没有被删掉,而当前序列的 a x a_{x} ax的前驱和后继也都没有被删掉,则元素 a x a_{x} ax在下一轮也不会成为被删除的点。
假设在某一轮,元素 a x a_{x} ax被删掉,则下一轮可能被删掉的点为其前驱和后继。
我们可以用 s e t set set记录下一轮有可能被删除的点的下标,用链表维护当前存在的序列。
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3e5 + 5;
int n;
int a[N], d[N];
bool st[N];
struct node
{
int b, pre, nxt;
} p[N];
vector<int>v, ans;
void solve()
{
cin >> n;
v.clear();
ans.clear();
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
cin >> d[i];
}
a[n + 1] = 0, d[n + 1] = 0;
p[0].pre = 0;
p[0].nxt = 1;
p[n + 1].pre = n;
p[n + 1].nxt = n + 1;
//初始化
for (int i = 1; i <= n; i++)
{
st[i] = false;
p[i].b = d[i];
p[i].nxt = i + 1;
p[i].pre = i - 1;
}
for (int i = 1; i <= n; i++)
{
if (p[i].b < a[p[i].pre] + a[p[i].nxt])
{
if (!st[i])
{
st[i] = true;
v.push_back(i);
}
}
}
for (int k = 1; k <= n; k++)
{
ans.push_back(v.size());
int low, high;
set<int>var;
for (int i = 0; i < v.size(); i++)
{
low = v[i];
high = v[i];
int j = i;
while (j + 1 < v.size() && p[v[j]].nxt == v[j + 1])
{
j++;
high = v[j];
}
if (p[low].pre >= 1)
var.insert(p[low].pre);
if (p[high].nxt <= n)
var.insert(p[high].nxt);
p[p[low].pre].nxt = p[high].nxt;
p[p[high].nxt].pre = p[low].pre;
i = j;
}
v.clear();
for (int i : var)
{
if (p[i].b < a[p[i].pre] + a[p[i].nxt])
{
if (!st[i])
{
st[i] = true;
v.push_back(i);
}
}
}
}
for (int val : ans)
{
cout << val << " ";
}
cout << 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;
}