CF 5 练习

A题:水题

B题:水题

C题:

用栈来做

D题:数学题,需要仔细地分类讨论

E题:

给你n个数围成一个环,若两个数之间没有比他们更大的数,则称两个数是一对合法的数

问n个数中共有几对数合法

类似于动态规划,一个相似的题目

先破环,变成一条线,把最大的元素放到两个端点(增加了一个元素)

用两个数组l[],r[]      

l[]记录某元素往左边第一个严格大于它的数的位置,

r[]记录某元素的右边第一个严格大于它的数的位置。

c[i]记录i位置的数与l[i]或r[i]之间等于num[i]的数的个数

具体见http://codeforces.com/blog/entry/213

代码写的有点搓

View Code
#include<cstdio>
#include<cstring>
const int maxn = 1000010;
int num[maxn],tmp[maxn];
int c[maxn],l[maxn],r[maxn];
int main()
{
    int n,i,j,k;
    while(scanf("%d",&n)!=EOF)
    {
        int Max=0,pos=-1;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
            tmp[i]=num[i];
            if(num[i]>Max)
            {
                    Max=num[i];
                    pos=i;
            }
        }
        for(i=1;i<=n&&pos+i-1<=n;i++)
        {
            num[i]=tmp[pos+i-1];
        }
        for(j=i,i=1;j<=n+1&&i<=pos;j++,i++)
        {
            num[j]=tmp[i];
        }
        l[1]=1;
        for(i=2;i<=n;i++)
        {
            l[i]=i-1;
            while(l[i]>1 && num[l[i]]<num[i]) l[i]=l[l[i]];
            if(l[i]>1 && num[l[i]]==num[i])
            {
                c[i]=c[l[i]]+1;
                l[i]=l[l[i]];
            }
        }
        __int64 ans=0;
        for(i=n;i>=2;i--)
        {
            ans+=c[i];
            r[i]=i+1;
            while(r[i]<=n && num[r[i]] < num[i]) r[i]=r[r[i]];
            if(r[i]<=n && num[r[i]]<=num[i])
            {
                r[i]=r[r[i]];
            }
            ans+=2;
            if(l[i]==1 && r[i]==n+1) ans--;
        }
        printf("%I64d\n",ans);

    }
    return 0;
}

 

posted @ 2012-05-28 02:55  Because Of You  Views(236)  Comments(0Edit  收藏  举报