您的位置:首页 > 产品设计 > UI/UE

Codechef Sam and Sequences(单调队列)

2015-03-03 19:28 344 查看
题目链接:http://www.codechef.com/problems/PRYS03/

这题只要考虑每个数字,最左和最右分别能延伸到的位置,然后就能计算出每个数字需要计算的次数,由于数字可能重复,所以对于左边维护到不大于的第一个数字位置,右边维护到小于的第一个数字位置,然后维护好后,在扫一遍计算总和即可

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N = 100005;

int t, n;
ll a
;

struct Node {
ll v;
int id;
Node() {}
Node (ll v, int id) {
this->v = v;
this->id = id;
}
} S
;

int left
, right
;

int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
S[0].id = 0;
int top = 0;
for (int i = 1; i <= n; i++) {
while (top && S[top].v > a[i]) top--;
left[i] = S[top].id;
S[++top] = Node(a[i], i);
}
S[0].id = n + 1;
top = 0;
for (int i = n; i >= 1; i--) {
while (top && S[top].v >= a[i]) top--;
right[i] = S[top].id;
S[++top] = Node(a[i], i);
}
ll ans = 0;
for (int i = 1; i <= n; i++)
ans += (ll)(i - left[i]) * (right[i] - i) * a[i];
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: