ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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\n",ans);
    }
    return 0;
}

 

posted on 2017-09-10 17:34  nul  阅读(370)  评论(0编辑  收藏  举报