Codeforces Round #346 (Div. 2) G 递推




链接:戳这里


G. Fence Divercity
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Long ago, Vasily built a good fence at his country house. Vasily calls a fence good, if it is a series of n consecutively fastened vertical boards of centimeter width, the height of each in centimeters is a positive integer. The house owner remembers that the height of the i-th board to the left is hi.

Today Vasily decided to change the design of the fence he had built, by cutting his top connected part so that the fence remained good. The cut part should consist of only the upper parts of the boards, while the adjacent parts must be interconnected (share a non-zero length before cutting out of the fence).

You, as Vasily's curious neighbor, will count the number of possible ways to cut exactly one part as is described above. Two ways to cut a part are called distinct, if for the remaining fences there is such i, that the height of the i-th boards vary.

As Vasily's fence can be very high and long, get the remainder after dividing the required number of ways by 1 000 000 007 (109 + 7).

Input
The first line contains integer n (1 ≤ n ≤ 1 000 000) — the number of boards in Vasily's fence.

The second line contains n space-separated numbers h1, h2, ..., hn (1 ≤ hi ≤ 109), where hi equals the height of the i-th board to the left.

Output
Print the remainder after dividing r by 1 000 000 007, where r is the number of ways to cut exactly one connected part so that the part consisted of the upper parts of the boards and the remaining fence was good.

Examples
input
2
1 1
output
0


input
3
3 4 2

output
13


Note
From the fence from the first example it is impossible to cut exactly one piece so as the remaining fence was good.

All the possible variants of the resulting fence from the second sample look as follows (the grey shows the cut out part):



题意:给出n块高度为hi的隔板组成的篱笆,要求削掉一个连通块(可以使一个格子也可以是多个)使得篱笆good,篱笆good的条件就是削掉后每个高度不为0,且不会被掏空,问有多少种削法


思路:我感觉画图更好理解吧,dp[i][j]表示当前的第i块隔板当做最后一块隔板的第j个格子的数量(当前的j做为要削的连通块的最右最下位置),当前隔板的高度为h[i](1<=j<=h[i])

分情况考虑:

1:h[i-1]<h[i]  

那么 (h[i-1]+1<=j<=h[i]) 的dp[i][j]=1,这个应该很好理解吧

(1<=j<=h[i-1])的位置的数量则为{ sigma(dp[i-1][j]) }+1   最后+1是表示当前的j格子本身作为一个连通块

2:h[i-1]>=h[i]

这样的话dp[i][j] (1<=j<=h[i]) 则为{ sigma(dp[i-1][j]) }+1  简单画图就可以知道了

但是这样设的状态肯定会T啊,所以我们可以采取递推的形似来模拟dp的过程,每个dp[i][]都只和前一项dp[i-1][]有关

所以我们在递推的时候存在具体的数据就可以了,然后维护下输出值,具体看代码吧


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
#define mod 1000000007
using namespace std;
ll h[1000100];
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%I64d",&h[i]),h[i]--;
    ll last=0,val=0,ans=0,x=0;
    for(int i=1;i<=n;i++){
        ans=(ans+h[i])%mod;
        if(h[i]>=h[i-1]){
            val=(h[i-1]-last+x*last%mod)%mod;
            ans=(ans+val*h[i-1]%mod)%mod;
            last=h[i-1];
            x=val+1;
        } else{
            if(h[i]>last) val=(h[i]-last+last*x%mod)%mod;
            else val=h[i]*x%mod;
            ans=(ans+val*h[i]%mod)%mod;
            last=h[i];
            x=val+1;
        }
    }
    printf("%I64d\n",ans%mod);
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值