HDU 5662 YJQQQAQ and the function

来源:互联网 发布:网络监控软件 编辑:程序博客网 时间:2024/05/17 06:10

题意:

长度为 n 的数组 A。他定义了一个函数fl,r,k,其中l,r,k 是满足lrr×kn 的正整数。函数值等于p×q×k,其中pAl×k,A(l+1)×k,...,Ar×k 的和值,而q 是这些数的最小值。YJQQQAQ想要仔细选择l,r,k 以最大化函数值。

思路:

枚举k,得到对应的序列。
然后对于这个序列来说,枚举最小值的位置,看这个最小值往左和往右最长能够延伸的位置,求出对应的和值,这个可以用单调栈来优化!这样就能得到这个序列下,最大的 pq 的值,最后取一下 max 就好了。

代码:

#include <cstdio>#include <iostream>#include <cmath>#include <vector>#define PB push_back#define FT first#define SD second#define MP make_pair#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int>  P;const int N = 3e5 + 10,MOD = 7+1e9;int n, a[N], R[N], L[N], st[N];LL sum[N];vector<int> G;LL gao(){    int m = G.size();    int top = 0;    for(int i = 0;i < m;++ i) {        L[i] = -1;        R[i] = m;        if(i == 0) sum[i] = G[i];        else sum[i] = sum[i-1] + G[i];    }    for(int i = 0;i < m;++ i) {        if(top == 0) st[top ++] = i;        else {            while(top != 0 && G[st[top-1]] > G[i]) {                R[st[top-1]] = i;                top --;            }            st[top ++] = i;        }    }    top = 0;    for(int i = m - 1;i >= 0;-- i) {        if(top == 0) st[top ++] = i;        else {            while(top != 0 && G[st[top-1]] > G[i]) {                L[st[top-1]] = i;                top --;            }            st[top ++] = i;        }    }    LL ans = 0, tmp;    for(int i = 0;i < m;i ++) {        if(L[i] == -1) tmp = 0;        else tmp = sum[L[i]];        ans = max(ans, 1LL * G[i] * (sum[R[i] - 1] - tmp));    }    return ans;}int main(){    int T;    scanf("%d", &T);    while(T --) {        scanf("%d", &n);        for(int i = 1;i <= n;++ i) scanf("%d", &a[i]);        LL ans = 0;        for(int k = 1;k <= n;k ++) {            G.clear();            for(int i = 1;i * k <= n;i ++) G.PB(a[i * k]);            ans = max(ans, 1LL * gao() * (int)sqrt(k + 0.5));        }        printf("%I64d\n", ans);    }    return 0;}
0 0