CF 5 练习

来源:互联网 发布:数据挖掘 数学基础 编辑:程序博客网 时间:2024/05/22 05:11

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;}

 

原创粉丝点击