Bad Hair Day [POJ3250] [单调栈 或 二分+RMQ]

题意
Farmer John的奶牛在风中凌乱了它们的发型……
每只奶牛都有一个身高hi(1 ≤ hi ≤ 1,000,000,000),现在在这里有一排全部面向右方的奶牛,一共有N只(1 ≤ N ≤ 80,000)。对于奶牛i来说,如果奶牛i+1,i+2,……,N这些奶牛的身高严格小于奶牛i,则奶牛i可以看到它们凌乱的发型。

输入
第一行 奶牛数量N
第二到 N+1行:第i+1行输入奶牛i的身高

输出
第一行:一个整数即c1到cN的和

样例输入
6
10
3
7
4
12
2

样例输出
5

分析
方法一
对于i,我们知道,令j∈[i+1,n],s=max(hi+1....hj)是具有单调性的(感性理解,j越大数字越多,同时j更小时的数也没有丢掉),所以如果s<=h[i]时,就可以继续向右扩张。使用二分查找,RMQ查询。RMQ可以使用ST达到O(1)的查询。

方法二
一头牛看到多少牛不好做,但可以被多少牛看到可解。只要在左边形成一个递减的数列,且最后一个大于当前的牛即可,数列大小即为当前牛的答案。可以用单调栈维护。

代码(法一)

 

 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register ll
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll unsigned long long
14 #define inf (1<<29)
15 #define maxn  80005
16 #define ls (pos<<1)
17 #define rs (pos<<1|1)
18 #define mid ((t[pos].l+t[pos].r)>>1)
19 using namespace std;
20 ll n,ANS;
21 ll num[maxn],mx[maxn][18];
22 inline ll read()
23 {
24     ll x=0,f=1;char c=getchar();
25     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
26     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
27     return x*f;
28 }
29 /*
30 void build(ll pos,ll l,ll r)
31 {
32     t[pos].l=l,t[pos].r=r;
33     if(l==r)    {t[pos].mx=num[l];return;}
34     build(ls,l,mid);build(rs,mid+1,r);
35     t[pos].mx=max(t[ls].mx,t[rs].mx);
36 }
37 
38 ll query(ll pos,ll l,ll r)
39 {
40     if(l<=t[pos].l&&t[pos].r<=r)    return t[pos].mx;
41     ll ans=0;
42     if(l<=mid)    ans=query(ls,l,r);
43     if(r>mid)    ans=max(ans,query(rs,l,r));
44     return ans;
45 }
46 */
47 
48 void ST()
49 {
50     rep(i,1,n) mx[i][0]=num[i];
51     rep(j,1,17)
52         rep(i,1,n)
53             if(i+(1<<j)-1<=n)
54                 mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
55 }
56 
57 int query(int l,int r)
58 {
59     int len=log(r-l+1)/log(2);
60     return max(mx[l][len],mx[r-(1<<len)+1][len]);
61 }
62 
63 int main()
64 {
65     n=read();
66     rep(i,1,n)    num[i]=read();
67     //build(1,1,n);
68     ST();
69     rep(i,1,n)
70     {
71         RG l=i+1,r=n,ans=i,md;
72         while(l<=r)
73         {
74             md=(l+r)>>1;
75             if(query(i+1,md)<num[i])    ans=md,l=md+1;
76             else                        r=md-1;
77         }
78         ANS+=ans-i;
79     }
80     cout<<ANS;
81     return 0;
82 }
View Code

 

posted @ 2018-07-20 22:00  iBilllee  阅读(187)  评论(0编辑  收藏  举报