【POJ2796】代碼,非原創,參考的別人的文章

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
/*
    Reference:http://www.cnblogs.com/youngxiao/archive/2010/05/19/1739381.html.THX A LOT TO YOU.
    author:YuXun Lu(A.K.A Kyle Broflovlaski)
    problem:poj2796
    Begin Time:13:00 p.m. 2/18/2012
    End Time: About 4 hours after that
    Test Data:
    6
    3 1 6 4 5 2
    7
    7 6 5 4 3 2 1
    9
    5 4 3 2 1 2 3 4 5
    Summary:
    思路和剪枝真的很重要。
    這道題明顯是一個思路上的優化就從TLE變成了ACCEPT
    還有一個重點就是cin和cout在效率方面跟printf和scanf差異巨大。
    以上。
    思路:
    設元素1....n,元素值v[1]...v[n],起始區間s[1]...s[n],結束區間e[1]..e[n]
    本題就是找到以元素i的元素值v[i]爲最小值的一個區間。
    因爲
    Happy Value : 區間元素值的和*區間最小元素值
    所以區間一定要最長,樸素的搜索一定會爆時間,我們可以採取如下策略剪枝:
    1.對於元素i,讀入元素i的元素值v[i],令j = i - 1;
    WHILE (j>0)
    IF v[i] < v[j] THEN
        j = s[j] - 1
    ELSE
        s[i] = j + 1
    ENDIF
    ENDW
    這就獲得了v[i]的起始地址,因爲如果v[j] > v[i]的話
    那麼v[j]對應的區間[s[j]...e[j]]肯定其中所有元素都比v[i]大
    因爲v[j]是其中最小的元素,我們把s[j]向左移動一個與s[i]比較,如果小於的話
    那麼該元素又成爲了新的v[j],如果大於的話移動回來就可以了。
    對於結束地址,也是一樣
    WHILE(j <= n+1)
    IF v[i] < v[j] THEN
        j = e[j] + 1
    ELSE
        e[i] = j - 1
    ENDIF
    ENDW
    但是注意到這個算法需要v[i]以1開始
    邊界條件爲v[0] = -1;v[n+1] = -1;否則根據條件,s[i]和e[i]取不到1和n;
    我們還要維護一個“和表”,其值爲
    sum[n] =  v[1] + v[2] + v[3] ... + v[n]
    這個簡單,讀取完了之後直接加到裏面就行了。
    最終輸出結果
    res = max(sum[e[i]] - sum[s[i] - 1] ) * v[i] );
    然後再輸出s[i],e[i]就可以了。
*/
using namespace std;
const long MAXSIZE = 100010 ;
long long v[MAXSIZE];
long long s[MAXSIZE];
long long e[MAXSIZE];
long long sum[MAXSIZE];

int main()
{
    long n;
 //   freopen("b:\\acm\\poj2796\\input.txt","r",stdin);
//while(cin >> n)
while(scanf("%d",&n) == 1)
{   long long maxv = -1;
    long p,q;
    v[n+1] = -1;
    sum[0] = 0;
    s[0] = 1;
    v[0] = -1;
    for(int i = 1 ; i <= n ; i++)
    {
        int j ;
        //cin >> v[i];
        scanf("%d",&v[i]);
        j = i - 1;
        while( j >= 0 )
        {
            if( v[i] > v[j])
            {
               s[i] = j + 1;
               break;
            }
            else
            //v[i] > v[j]
            {
              j = s[j] - 1;
            }
        }
        sum[i] = sum[i-1] + v[i];
    }
    for(int i = n; i > 0 ; i--)
    {
        int j ;
        j = i + 1;
        while( j <= n + 1)
        {
            if(v[i] > v[j])
            {
                e[i] = j - 1;
                break;
            }
            else
            {
                j = e[j] + 1;
            }
        }
    }

    for(int i = 1; i <= n ; i ++)
    {
        if(v[i]*(sum[e[i]] - sum[s[i]-1]) > maxv)
        {
            maxv = v[i]*(sum[e[i]] - sum[s[i]-1]);
            p = s[i];
            q = e[i];
        }
    }
    //cout << maxv << endl;
    //cout << p << " " << q << endl;
    printf("%I64d\n",maxv);
    printf("%d %d",p,q);
}
   // cout << "Hello world!" << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章