Description

宅邸迅速的燃烧着,必须带贝蒂走出禁书库!凭着感觉,又一次直接找到禁书库的门。
“你,是那个人嘛?”400年了,当初圣域建立结界时没有进入圣域,被伤了心的人工精灵贝蒂,与强欲魔女签订契约,守护宅邸的禁书库,直至“那个人”的到来,那个人会解开贝蒂的心结。
“我不是那个什么人,但我会成为你唯一的人。我会给你幸福!”
精灵与人签订契约,从此相依为命。这便是,永恒的契约。

宅邸里,罗兹瓦尔的房间图书柜后,有一条链接宅邸和圣域的秘密通道,其中有一个神奇的大回环,由 n    n   块石头组成。
第i块石头有一个高度 ai    a i   ,两块不同的石头i,j能够互相看到,则它们在环上的两条路径中有至少一条路径上除了两个端点(即 i,j    i , j   )路径上石头高度都不大于min(ai,aj) m i n ( a i , a j ) 。
被罗兹瓦尔雇佣的猎肠者躲在这秘密的通道中,为了能够更好的观察通道中的情况,她想知道有多少对石头能够互相看到。

Input

第一行一个正整数 T    T   ,表示数据组数。
接下来 T    T   组数据,每组数据第一行读入正整数 n    n   ,接下来一行按顺时针顺序读入序列 a    a   表示石块的高度。

Output

 T    T   行表示每组数据的答案。

Sample Input

1
5
1 2 4 5 3

Sample Output

7

Data Constraint

40%,n≤200 40 % , n ≤ 200
60%,n≤2000 60 % , n ≤ 2000
70%,n≤100000 70 % , n ≤ 100000
80%,n≤1000000,1≤ai≤1000000 80 % , n ≤ 1000000 , 1 ≤ a i ≤ 1000000
100%,n≤1000000,T≤5,1≤ai≤1000000000 100 % , n ≤ 1000000 , T ≤ 5 , 1 ≤ a i ≤ 1000000000

solution

首先对于像这种对于环的题目一般首先会有这样的思路:
①将这段序列复制一段
②选一个作“起点”,该起点的作用就是可以断绝前后关系。

比如这道题,我们就选最大的 ai    a i   作起点,若存在多个最大点则任选一个,不影响。
接下来就谈谈做法吧。
我们设 a1    a 1   为最大值,那么该序列就变为 a1,a2,a3,...an    a 1 , a 2 , a 3 , . . . a n   ,另外注意在最后再加一个 an+1=a1    a n + 1 = a 1   ,表示首尾相接。

无畏契约出现a javascript 无畏契约出现physxcpu_数据 无畏契约出现a javascript 无畏契约出现physxcpu_无畏契约出现a javascript_02   且能互相看见的对数。

由 ai<aj    a i < a j   易得 ∀a[i+1..j−1]≤ai   ∀ a [ i + 1.. j − 1 ] ≤ a i ,所以能与 ai    a i   匹配的 aj    a j   是第一个比 ai    a i   大的数,即存在唯一性!
我们设这个 aj    a j   为 next[i]   n e x t [ i ] 。
所以除了 ai=a1    a i = a 1   的 ai    a i   外(即为该数亦为最大值),其实全部的 ai    a i   都有与之对应的 next[i]   n e x t [ i ] ,可以线性统计答案,具体来讲就是单调栈维护不上升序列
但是为了保证不算重,所以我们要将那些 aj=an+1 a j = a n + 1 (即 a1    a 1   ) 的数打上 tag   t a g ,然后我们倒过来再做一遍统计答案,遇到带有 tag    t a g   且 next[i]=a1    n e x t [ i ] = a 1   的就不必算入答案内。

无畏契约出现a javascript 无畏契约出现physxcpu_无畏契约出现a javascript_03 的情况呢

显然我们也可以在单调栈中统计连续的数出现的次数。
神马?还不懂?如果出现次数是 z    z   ,那不就有z∗(z−1)/2 z ∗ ( z − 1 ) / 2 吗?

code

#include<cstdio> 
#define maxn 1000005
using namespace std;
int a[2*maxn],dt[2*maxn],p[2*maxn];
long long ans,z,d;
int st,t,n,i,j,ma,t2;
int main(){
    freopen("forever.in","r",stdin);
    freopen("forever.out","w",stdout);
    scanf("%d",&t);
    for (int t2=1;t2<=t;t2++){
        scanf("%d",&n);     
        ans=0;ma=0;
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i+n]=a[i];
            if (a[i]>ma){
                st=i;
                ma=a[i];
            }
        }
        d=1;dt[d]=st;
        for (int i=st+1;i<=st+n;i++){
            p[i]=0;
            if (a[i]>a[i-1])
                while ((d>0)&&(a[i]>a[dt[d]]) ){
                    ans++;
                    if (i==st+n) p[dt[d]]=1;
                    if (a[dt[d]]==a[dt[d+1]]) z++; else{
                        ans+=z*(z+1)/2;
                        z=0;
                    }
                    d--;
                }
            ans+=z*(z+1)/2;z=0;
            dt[++d]=i;dt[d+1]=0;
        }
        ans+=(d-1)*(d-2)/2;
        d=1;dt[d]=st+n;
        for (int i=st+n-1;i>=st;i--){
            if (a[i]>a[i+1]) while ((d>0)&&(a[i]>a[dt[d]])){
                if ((i!=st) || ((i==st)&&(!p[dt[d]])))ans++;
                d--;
            } 
            dt[++d]=i;dt[d+1]=0;
        }
        printf("%lld\n",ans);
    }
    fclose(stdin);
    fclose(stdout);
}