2014湘潭邀请赛 C题 湘大OJ 1205 Range (单调栈)

Problem Description

For an array, the range function is defined below: Range(A)=Max(A)-Min(A)+1; For example, suppose A={1,2,3,4,5}, then Range(A)=5-1+1=5. Now, given an array A(length≤100000), you are going to calcalute the sum of all subarray‘s range. i.e sigma(i,j){Range(A[i,j])}.

Input

First line contain an integer T, there are T(1≤T≤100) cases. For each case T. The length N(1≤N≤100000), and N integers A[i](1≤A[i]≤109).

Output

Output case number first, then the answer.

Sample Input

1
5
1 2 3 4 5

Sample Output

Case 1: 35

实际上就是求出以第i个数为最大值得区间个数 和 以第i个数为最小值得区间个数 ,可以利用单调栈的思想,和poj2559几乎是一个题。都是求出以第i个为最值,往左往右能扩展出的范围。

#include <iostream>
#include <cstdio>
using namespace std;
typedef __int64 LL;
const int maxn = 100000+10;
int t, n;
LL l[maxn], r[maxn], a[maxn];
LL solve()
{
    LL ans = (LL)(n+1)*n/2;
    l[1] = 1;
    for(int i = 2; i <= n; i++) {
        int tmp = i;
        while(tmp > 1 && a[tmp-1] >= a[i]) tmp = l[tmp-1];
        l[i] = tmp;
    }
    r[n] = n;
    for(int i = n-1; i > 0; i--) {
        int tmp = i;
        while(tmp < n && a[tmp+1] > a[i]) tmp = r[tmp+1];
        r[i] = tmp;
    }
    for(int i = 1; i <= n; i++) ans -= a[i] * (LL)(i - l[i] + 1) * (LL)(r[i] - i + 1);
    l[1] = 1;
    for(int i = 2; i <= n; i++) {
        int tmp = i;
        while(tmp > 1 && a[tmp-1] <= a[i]) tmp = l[tmp-1];
        l[i] = tmp;
    }
    r[n] = n;
    for(int i = n-1; i > 0; i--) {
        int tmp = i;
        while(tmp < n && a[tmp+1] < a[i]) tmp = r[tmp+1];
        r[i] = tmp;
    }
    for(int i = 1; i <= n; i++) ans += a[i] * (LL)(i - l[i] + 1) * (LL)(r[i] - i + 1);

    return ans;
}
int main()
{
    cin >> t;
    for(int ca = 1; ca <= t; ca++) {
        cin >> n;
        for(int i = 1; i < n+1; i++) scanf("%I64d", &a[i]);
        printf("Case %d: %I64d\n", ca, solve());
    }
    return 0;
}



时间: 2024-10-14 13:57:31

2014湘潭邀请赛 C题 湘大OJ 1205 Range (单调栈)的相关文章

2014 BNU 邀请赛E题(递推+矩阵快速幂)

Elegant String 题意:给定一个字符串,由0-k数字组成,要求该串中,子串不包含0-k全排列的方案数 思路:dp[i][j]表示放到i个数字,后面有j个不相同,然后想递推式,大概就是对应每种情况k分别能由那几种状态转移过来,在纸上画画就能构造出矩阵了,由于n很大,所以用快速幂解决 代码: #include <stdio.h> #include <string.h> const long long MOD = 20140518; int t; long long n; i

2014 BNU 邀请赛A题(构造问题)

A Matrix 题意:按照题目中给定的方法,给你一个矩阵,求出变换出该矩阵的字符串 思路:构造问题,在纸上多画几组就能发现,每次必须从上往下找到一条路径,最后输出这些路径,按照开头最大的最晚输出,找的过程中只要不断往下一层找一个大的即可,并且如果一开使有一行是非递增就是错误 代码: #include <stdio.h> #include <string.h> #include <vector> #include <map> using namespace

BNUOJ 34985 Elegant String 2014北京邀请赛E题 动态规划 矩阵快速幂

Elegant String Time Limit: 1000msMemory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,-, k

BNUOJ 34985 Elegant String 2014北京邀请赛E题 矩阵快速幂

题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 题目大意:问n长度的串用0~k的数字去填,有多少个串保证任意子串中不包含0~k的某一个全排列 邀请赛上A的较多的一道题,比赛的时候死活想不出,回来之后突然就想通了,简直..... = =! 解题思路: 对于所有串我们都只考虑末尾最多有多少位能构成全排列的一部分(用l来表示),即最多有多少位不重复的数字出现,将问题转化为求末尾最多有k位能构成全排列的串的总数量 假设k为5,有一个

2014北京邀请赛E题-矩阵快速幂

题意:长度为n(1<=n<=10^18)的并且任意连续子串都不是0-k(1<=k<=9)的一个排列的字符串有多少种. 解法:矩阵快速幂.dp[i][j]表示i长度最后连续j个不同(即最后j个无重复,最后j+1个有重复)的字符串的个数.状态选好很重要.设计状态时最重要考虑是唯一性和可传递性,比赛时明明知道肯定是矩阵快速幂,但是一直没想到这个状态表示,自己设计的自己都不会转移. dp[i][j]有了后,后边加一个字符,这个字符可以是j之内的任意一个,也可以是j以外的,这样枚举每种情况,

ACM--模拟--湘大OJ 1184--A Love Letter--水

湘大OJ题目地址:传送门 A Love Letter Time Limit : 1000 MS  Memory Limit : 65536 KB 题目描述 CodeMonkey终于下定决心用情书的方式向心爱的女神表白,当他历经几天几夜写完之后才知道女神有很多不喜欢的词,所以他不得不有把这些词删掉.例如:原文是:ILOVEYOU,女神不喜欢的词是'LV','O'那么最终情书要改成IEYU.现在已知女生不喜欢的词的集合S,CodeMonkey想知道刚写的情书会改成什么样?S={"HATE"

ACM--数学--湘大oj 1088--Cycloid

湘大oj题目地址:传送门 Cycloid 时间限制:1000 ms  |  内存限制:65536 KB Description A cycloid is the curve traced by a point on the rim of a circular wheel as the wheel rolls along a straight line. It is an example of a roulette, a curve generated by a curve rolling on

2014 BNU 邀请赛B题(枚举)

Beautiful Garden 题意:x轴上放了一些树,现在要移动一些树使得所有树都等间距,问最少要移动多少棵 思路:枚举,枚举第一棵树,和另一棵树,以及中间有多少树,这样就能知道等差数列的首项和公差,然后再循环一边计算出答案,保存最小值 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; #define

2014 BNU邀请赛F题(枚举)

Football on Table 题意:一些杆上有人,人有一个宽度,然后现在有一个球射过去,要求出球不会碰到任何人的概率 思路:计算出每根杆的概率,之后累乘,计算杆的概率的时候,可以先把每块人的区间长度再移动过程中会覆盖多少长度累加出来,然后(1?总和/可移动距离)就是不会碰到的概率 代码: #include <stdio.h> #include <string.h> #include <math.h> const double eps = 1e-8; int t,