hdu 5696 区间的价值

套路题

求出来以每个数为最大值/最小值时的一个区间范围, 然后枚举每个数为最大值的情况更新即可, 但是对于重复数的话需要特判一下, 假如用map记录来特判复杂度就是$O(nlogn)$, 不过题目说了数据随机, 数字几乎不重复, 没特判直接跑了Rank2

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;


const int N = 1e6+10;

int n;
int a[N], b[N], L[N], R[N], LL[N], RR[N];
ll ans[N];
void chkmax(ll &x, ll y) {x=max(x,y);}

void work() {
    REP(i,1,n) scanf("%d", a+i);
    REP(i,1,n) ans[i]=0;
    REP(i,1,n) {
        LL[i]=L[i]=i-1;
        while (L[i]&&a[i]>=a[L[i]]) L[i]=L[L[i]];
        while (LL[i]&&a[i]<=a[LL[i]]) LL[i]=LL[LL[i]];
    }
    PER(i,1,n) {
        RR[i]=R[i]=i+1;
        while (R[i]<=n&&a[i]>=a[R[i]]) R[i]=R[R[i]];
        while (RR[i]<=n&&a[i]<=a[RR[i]]) RR[i]=RR[RR[i]];
    }
    REP(i,1,n) {
        pii mi(a[i],i);
        PER(j,L[i]+1,i-1) {
            mi = min(mi, pii(a[j],j));
            chkmax(ans[RR[mi.y]-j],(ll)mi.x*a[i]);
        }
        mi = pii(a[i],i);
        REP(j,i+1,R[i]-1) {
            mi = min(mi, pii(a[j],j));
            chkmax(ans[j-LL[mi.y]],(ll)mi.x*a[i]);
        }
    }
    REP(i,1,n) ans[1]=max(ans[1],(ll)a[i]*a[i]);
    PER(i,1,n) ans[i]=max(ans[i],ans[i+1]);
    REP(i,1,n) printf("%lld\n",ans[i]);
}

int main() {
    for (; ~scanf("%d", &n); ) work();
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10492861.html
今日推荐