不难发现连通块一定是连续的一段。考虑枚举连通块的右端点 \(p\),要求 \([1,p]\) 和 \([p+1,n]\) 之间没有连边,即 \(\min\limits_{1 \leqslant i \leqslant p} a_i > \max\limits_{p+1 \leqslant i \leqslant n} a_i\)。
设 \(w=\max\limits_{p+1 \leqslant i \leqslant n} a_i\),将 \(>w\) 的位置设为 \(1\),\(\leqslant w\) 的位置设为 \(0\)。合法的 \(w\) 一定会得到一个形如 \(1111100000\) 的 \(01\) 序列,\(1\) 的个数为 \(p\),枚举 \(w\) 就等价于枚举 \(p\)。
设 \(a_0=\infty,a_{n+1}=0\),合法的 \(w\) 对应的 \(01\) 序列中只有一对相邻的 \(1,0\),当 \(w\in\left[ \min\{a_i,a_{i+1}\},\max\{a_i,a_{i+1}\} \right)\) 时会产生一对相邻的 \(1,0\)。
那么在线段树上维护值域,维护区间最小值,当最小值为 \(1\) 时,该区间才能产生贡献。
#include<bits/stdc++.h>
#define maxn 1000010
#define maxm 4000010
#define all 1000001
#define ls (cur<<1)
#define rs (cur<<1|1)
#define mid ((l+r)>>1)
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,q,root=1;
int a[maxn],mn[maxm],val[maxm],tag[maxm];
void pushup(int cur)
{
if(mn[ls]<mn[rs]) mn[cur]=mn[ls],val[cur]=val[ls];
else if(mn[ls]>mn[rs]) mn[cur]=mn[rs],val[cur]=val[rs];
else mn[cur]=mn[ls],val[cur]=val[ls]+val[rs];
}
void pushtag(int cur,int v)
{
mn[cur]+=v,tag[cur]+=v;
}
void pushdown(int cur)
{
if(!tag[cur]) return;
pushtag(ls,tag[cur]),pushtag(rs,tag[cur]),tag[cur]=0;
}
void update(int l,int r,int pos,int v,int cur)
{
if(l==r)
{
val[cur]+=v;
return;
}
pushdown(cur);
if(pos<=mid) update(l,mid,pos,v,ls);
else update(mid+1,r,pos,v,rs);
pushup(cur);
}
void modify(int L,int R,int l,int r,int v,int cur)
{
if(L>R) return;
if(L<=l&&R>=r)
{
pushtag(cur,v);
return;
}
pushdown(cur);
if(L<=mid) modify(L,R,l,mid,v,ls);
if(R>mid) modify(L,R,mid+1,r,v,rs);
pushup(cur);
}
int query(int L,int R,int l,int r,int cur)
{
if(L<=l&&R>=r) return mn[cur]==1?val[cur]:0;
int v=0;
pushdown(cur);
if(L<=mid) v+=query(L,R,l,mid,ls);
if(R>mid) v+=query(L,R,mid+1,r,rs);
return v;
}
int main()
{
read(n),read(q),a[0]=all;
for(int i=1;i<=n;++i) read(a[i]),update(0,all,a[i],1,root);
for(int i=0;i<=n;++i)
modify(min(a[i],a[i+1]),max(a[i],a[i+1])-1,0,all,1,root);
while(q--)
{
int x;
read(x),update(0,all,a[x],-1,root);
modify(min(a[x],a[x+1]),max(a[x],a[x+1])-1,0,all,-1,root);
modify(min(a[x-1],a[x]),max(a[x-1],a[x])-1,0,all,-1,root);
read(a[x]),update(0,all,a[x],1,root);
modify(min(a[x],a[x+1]),max(a[x],a[x+1])-1,0,all,1,root);
modify(min(a[x-1],a[x]),max(a[x-1],a[x])-1,0,all,1,root);
printf("%d\n",query(1,all-1,0,all,root));
}
return 0;
}