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