题目链接
题解
- 这题可以通过线段树的方法较为轻松的解决,而我的这个方法更为暴力。
- 我们可以考虑维护以下两个操作:
-
m
e
r
g
e
(
x
,
y
)
merge(x, y)
merge(x,y)令这两个位置的集合进行暴力合并
– s p l i t ( x ) split(x) split(x)使得位置 x x x的数从集合中脱离出来
– 用 m u l t i s e t multiset multiset维护每个区间的长度,用 s e t < p a i r > set<pair> set<pair>来维护每个区间的左右区间 - 对于 m e r g e ( x , y ) merge(x,y) merge(x,y)这个操作,通过 l o w e r _ b o u n d lower\_bound lower_bound找出包含 x x x和 y y y的两个区间,从维护长度和区间的集合中删除这两个区间,再添加合并后的区间即可。
- 对于 s p l i t ( x ) split(x) split(x)这个操作,我们通过 l o w e r _ b o u n d lower\_bound lower_bound找出 x x x所在的区间,并对其进行分类讨论,按照其在区间内部,首部和尾部三种情况进行拆分。
- 对于 x x x所在的区间 [ L , R ] [L,R] [L,R]:
- 若 L = x L = x L=x,可以将其拆成 [ x , x ] [x,x] [x,x]与 [ x + 1 , R ] [x+1,R] [x+1,R]两个区间。
- 若 R = x R = x R=x,可以将其拆成 [ L , x − 1 ] [L,x-1] [L,x−1]与 [ x , x ] [x,x] [x,x]两个区间。
- 否则,将其拆成 [ L , x − 1 ] , [ x , x ] , [ x + 1 , R ] [L,x-1],[x,x],[x+1,R] [L,x−1],[x,x],[x+1,R]三个区间。
- 在处理完如上操作后,我们可以方便地得出答案,就是储存区间的 s e t set set的 r b e g i n rbegin rbegin迭代器的值
- 至此,我们便完成了对这个问题的讨论,就大功告成啦(悲)(大嘘)
#include<bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl;
#define IO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(3)
using namespace std;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
int n, q;
multiset<int> l;
set<pair<int, int>> x;
int a[maxn];
void merge(int i, int j)
{
if(i == 0 || j == n + 1)
return ;
if(i > j)swap(i, j);
auto it = x.lower_bound({i, 0});
auto it2 = x.lower_bound({j, 0});
if(it->second != i)it --;
if(it2->first != j)it2 --;
pair<int, int> s1 = *it;
pair<int, int> s2 = *it2;
x.insert({s1.first, s2.second});
x.erase(s1);
x.erase(s2);
l.insert(s2.second - s1.first + 1);
l.erase(l.find(s2.second - s2.first + 1));
l.erase(l.find(s1.second - s1.first + 1));
}
void split(int i)
{
auto it = x.lower_bound({i, 0});
if(i == it->first && i == it->second)
return ;
if(i < it->first || i > it->second)
it --;
pair<int, int> pr = *it;
int le = pr.second - pr.first + 1;
if(pr.first == i || i == 1)
{
x.insert({i, i});
x.insert({i + 1, pr.second});
x.erase(pr);
l.insert(1);
l.insert(le - 1);
l.erase(l.find(le));
return ;
}
if(pr.second == i || i == n)
{
x.insert({i, i});
x.insert({pr.first, i - 1});
x.erase(pr);
l.insert(1);
l.insert(le - 1);
l.erase(l.find(le));
return ;
}
int llen = i - pr.first, rlen = pr.second - i;
x.insert({pr.first, i - 1});
x.insert({i, i});
x.insert({i + 1, pr.second});
x.erase(x.find(pr));
l.insert(1);
l.insert(llen);
l.insert(rlen);
l.erase(l.find(le));
}
void solve()
{
cin >> n >> q;
for(int i = 1; i <= n; i ++)
l.insert(1);
for(int i = 1; i <= n; i ++)
x.insert({i, i});
for(int i = 1; i <= q; i ++)
{
int t;
cin >> t;
a[t] ^= 1;
if(a[t] == a[t - 1] || a[t] == a[t + 1])
split(t);
if(a[t] != a[t + 1])
merge(t, t + 1);
if(a[t] != a[t - 1])
merge(t - 1, t);
cout << *l.rbegin() << '\n';
}
}
signed main()
{
IO
solve();
return 0;
}