CF1270H Number of Components

不难发现连通块一定是连续的一段。考虑枚举连通块的右端点 \(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\)

在线段树上维护值域,维护每个 \(w\) 的出现次数和其产生相邻 \(10\) 的个数,个数为 \(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;
}
posted @ 2021-01-24 19:53  lhm_liu  阅读(196)  评论(0编辑  收藏  举报