原题解链接:https://ac.nowcoder.com/discuss/149978
定义数组 ,其中 . 当 时, ;否则 。
则所求 中最长的连续的 1 的长度 。
对于 的修改相当于对于 和 的修改,所以下面只用考虑对 的修改。
定义数组 ,其中 表示 中有多少段极长的连续的 1 的长度为 ,特别的, 。
求答案时只要找到满足 的 即可。
考虑当 从 0 改成 1 时如何维护 。
求出从 起向左的极长的连续的 1 的长度 left_len 和从 起向右的极长的连续的 1 的长度 right_len,
-- cnt[left_len]; --cnt_[right_len]; ++cnt[left_len+right_len }+1];
即可。
当从改成时同理,只是把减换成加,加换成减。
时间复杂度
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)
const int N=1e5+5;
int n,a[N];
bool b[N];
int cnt[100];
void modify_b(int x)
{
if(b[x]==(a[x]<a[x+1]))return ;
b[x]^=1;
int l=x;
while(b[l-1])--l;
int r=x+1;
while(b[r])++r;
if(b[x])
{
++cnt[r-l];--cnt[x-l];--cnt[r-(x+1)];
}
else
{
--cnt[r-l];++cnt[x-l];++cnt[r-(x+1)];
}
}
void modify_a(int x,int y)
{
a[x]=y;
if(x!=1)modify_b(x-1);
if(x!=n)modify_b(x);
}
int query()
{
int i=99;
while(!cnt[i])--i;
return i+1;
}
int main()
{
// freopen("1.in","r",stdin);
int m;
cin>>n>>m;
cnt[0]=1e9;
rep(i,1,n)
{
int x;
scanf("%d",&x);
modify_a(i,x);
}
printf("%d\n",query());
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
modify_a(x,y);
printf("%d\n",query());
}
}