zoukankan      html  css  js  c++  java
  • bzoj5011: [Jx2017]颜色

    Description

    可怜有一个长度为n的正整数序列Ai,其中相同的正整数代表着相同的颜色。
    现在可怜觉得这个序列太长了,于是她决定选择一些颜色把这些颜色的所有位置都删去。
    删除颜色i可以定义为把所有满足Aj=i的位置j都从序列中删去。
    然而有些时候删去之后,整个序列变成了好几段,可怜不喜欢这样,于是她想要知道有多
    少种删去颜色的方案使得最后剩下来的序列非空且连续。
    例如颜色序列{1,2,3,4,5},删除颜色3后序列变成了{1,2}和{4,5}两段,不满足条件。
    而删除颜色1后序列变成了{2,3,4,5},满足条件。
    两个方案不同当且仅当至少存在一个颜色i只在其中一个方案中被删去 。

    Input

    第一行输入一个整数T表示数据组数。
    每组数据第一行输入一个整数n表示数列长度。
    第二行输入n个整数描述颜色序列。
    1 ≤ T, ∑ n ≤ 3 × 10^5, 1 ≤ Ai ≤ n

    Output

    对于每组数据输出一个整数表示答案
    对每种颜色,只能全选或全不选,将区间[L,R]看作平面上的点(L,R),则限制条件是矩形内的点不能选,可以用线段树维护扫描线进行统计。
    #include<bits/stdc++.h>
    char buf[10000007],*ptr=buf;
    int _(){
        int x=0;
        while(*ptr<48)++ptr;
        while(*ptr>47)x=x*10+*ptr++-48;
        return x;
    }
    const int N=3e5+7;
    int T,n;
    int a[N],pe[N],pb[N],pv[N],nx[N];
    long long ans;
    int min(int a,int b){return a<b?a:b;}
    int _l,_r,_a;
    struct node{
        node*lc,*rc;
        int L,R,M;
        int mn,mt,a;
        void add(int x){
            mn+=x,a+=x;
        }
        void dn(){
            if(a){
                lc->add(a);
                rc->add(a);
                a=0;
            }
        }
        void up(){
            mn=min(lc->mn,rc->mn);
            mt=(mn==lc->mn?lc->mt:0)+(mn==rc->mn?rc->mt:0);
        }
        void add(){
            if(_l<=L&&R<=_r)return add(_a);
            dn();
            if(_l<=M)lc->add();
            if(_r>M)rc->add();
            up();
        }
        int c0(){
            return mn?0:mt;
        }
    }ns[N*2],*np,*rt;
    node*build(int L,int R){
        node*w=np++;
        w->L=L,w->R=R;
        w->mn=w->a=w->M=0;
        w->mt=R-L+1;
        if(L<R){
            int M=w->M=L+R>>1;
            w->lc=build(L,M);
            w->rc=build(M+1,R);
        }
        return w;
    }
    void add(int l,int r,int a){
        _l=l,_r=r,_a=a;
        if(l<=r)rt->add();
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin);
        for(T=_();T;--T){
            n=_();ans=0;
            np=ns;
            rt=build(1,n);
            for(int i=1;i<=n;++i)a[i]=_(),pe[i]=0,pb[i]=n+1;
            for(int i=1,x;i<=n;++i)x=a[i],pv[i]=pe[x],pe[x]=i;
            for(int i=n,x;i>=1;--i)x=a[i],nx[i]=pb[x],pb[x]=i;
            add(1,n,1);
            for(int i=n,x;i;--i){
                x=a[i];
                add(i+1,nx[i]-1,1);
                if(i==pb[x])add(pe[x],n,-1);
                ans+=rt->c0();
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    使用VisualVM检测
    《自控力》读书笔记
    【转】Oracle索引的类型
    【转】Oracle索引HINT的使用
    【转】Oracle 执行计划(Explain Plan) 说明
    Oracle分区
    【转】Oracle索引失效问题
    【转】《从入门到精通云服务器》第七讲—负载均衡和CDN技术
    【转】《从入门到精通云服务器》第七讲—IAAS、PAAS、SAAS
    【转】《从入门到精通云服务器》第六讲—OpenStack基础
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7501631.html
Copyright © 2011-2022 走看看