• CF1270H Number of Components


    Link
    不难发现,每个连通块都是原序列中连续的一段。
    假如有一个连通块的右端点为(p),那么合法的条件为(minlimits_{iin[1,p]}a_i>maxlimits_{iin(p,n]}a_i)
    枚举(w=maxlimits_{iin(p,n]}a_i),将序列中不大于(w)的位置设成(0),大于(w)的位置设成(0),那么合法的(p)当且仅当序列为(p imes 1+(n-p) imes0)
    那么我们只需要统计有多少个(w=a_i)对应的(01)序列为(p imes 1+(n-p) imes0)的形式即可,为了方便设(a_0=+infty,a_{n+1}=0)
    用线段树维护对每一个(w)维护它对应的(01)序列中相邻(10)对的数量和(w)在序列中的出现次数。
    对于任意一个(w)至少会存在一个(10)对,因此维护最小值以及最小值的数量即可。

    #include<cctype>
    #include<cstdio>
    const int N=500007;
    char ibuf[1<<24],*iS=ibuf;int a[N],cnt[2*N],t[8*N],tag[8*N];
    int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l+r)/2)
    void pushup(int p,int l,int r){t[p]=(l==r? !!cnt[l]:t[ls]+t[rs])*!tag[p];}
    void update(int p,int l,int r,int L,int R,int x)
    {
        if(L>r||l>R||L>R) return ;
        if(L<=l&&r<=R) return tag[p]+=x,pushup(p,l,r),void();
        update(ls,l,mid,L,R,x),update(rs,mid+1,r,L,R,x),pushup(p,l,r);
    }
    #undef ls
    #undef rs
    #undef mid
    void change()
    {
        int p=read(),x=read();
        update(1,1,1000000,a[p-1]+1,a[p],-1),update(1,1,1000000,a[p]+1,a[p+1],-1),--cnt[a[p]],update(1,1,1000000,a[p],a[p],0);
        ++cnt[a[p]=x],update(1,1,1000000,a[p],a[p],0), update(1,1,1000000,a[p-1]+1,a[p],1),update(1,1,1000000,a[p]+1,a[p+1],1);
        printf("%d
    ",t[1]);
    }
    int main()
    {
        fread(ibuf,1,1<<24,stdin);
        int n=read(),m=read();a[0]=1e9;
        for(int i=1;i<=n;++i) ++cnt[a[i]=read()],update(1,1,1000000,a[i],a[i],0),update(1,1,1000000,a[i-1]+1,a[i],1);
        while(m--) change();
    }
    
  • 相关阅读:
    多线程
    异常
    接口
    多态
    对象和封装
    DIV+CSS命名规范集合
    MySql 最新官方安装教程-下载
    乐嘉性格色彩-4色特性,学习感悟
    Eclipse 的常用快捷方式
    学习方法_2011年编写和锻炼的思维题
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12988194.html
Copyright © 2020-2023  润新知