CodeForces 484D Kindergarten

题意:

将含有n(10^6)个元素的序列a划分成几段  每段为连续的一些元素  每段的价值为段中最大值减去最小值  总价值为所有段的价值和  求  最大的总价值

思路:

不难想到一个dp的转移方程 dp[i] = max( dp[j] + max(a[j+1]...a[i]) - min(a[j+1]...a[i]) )  但是dp是n^2的会TLE

注意观察转移方程  其中的max-min的部分很有特点  因为只关心这段区间的max和min  所以其他值都是没必要的  那么没有必要的值如果放在区间的端点  则将它划分到区间外一定会得到一个不更坏的答案  因此可以想到  max和min一定是区间的端点  那么这个区间是单调的  这个结论也很容易想出了

很明显  这样单调的区间应该划分在一起  可以画数轴看一下  不划分在一起就会少覆盖

至此已经得出本题的策略  单调的区间分一组

考虑细节  端点!!  样例 3 5 2 告诉我们端点应该特别考虑  因此我们可以在端点处特判它是放在左边区间更优还是右边区间更优  然后就可以O(n)的dp了  每次转移只与单调区间端点有关

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 1000010

int a[N];
int n;
LL dp[N], ans;

int cmp(int x, int y) {
	if (x < y)
		return -1;
	if (x > y)
		return 1;
	return 0;
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int l = 1; l < n;) {
		int r = l + 1;
		int sign = cmp(a[l], a[r]);
		dp[r] = max(dp[r], dp[l]);
		r++;
		while (r <= n) {
			if (sign != cmp(a[r - 1], a[r]))
				break;
			dp[r] = max(dp[r], dp[r - 1]);
			r++;
		}
		r--;
		for (int i = max(1, l); i <= l + 1 && i < r; i++) {
			for (int j = max(r - 1, i + 1); j <= r + 1 && j <= n; j++) {
				dp[j] = max(dp[j], dp[i - 1] + abs(a[j] - a[i]));
			}
		}
		l = r;
	}
	cout << dp[n] << endl;
	return 0;
}
时间: 2024-10-14 06:42:07

CodeForces 484D Kindergarten的相关文章

Codeforces 484D Kindergarten(dp)

题目链接:Codeforces 484D Kindergarten 题目大意:给定一个序列,可以分为若干段,每份的值即为该段中的最大值减掉最小值.问说所有段的总和最大为多少. 解题思路:dp[i][j],表示第i个位置,j为0时为升序状态,j为1是为降序状态.根据a[i]和a[i-1]的大小可以确定升降序的转 移.比如1 5 5 7,在第2个5的位置,即使出现了相等的情况,也会是分段的情况会更优:1 5 6 7 只有连续升序的状态 才需要考虑说是否成段. #include <cstdio> #

codeforces 484D Kindergarten (dp、贪心)

题意:给n个数,分成若干个连续组,每组获益为max-min,输出最大获益. 参考:http://blog.csdn.net/keshuai19940722/article/details/40873581 参考的链接里说得很明白了,我的dp[i][0]是升序,dp[i][1]是降序,习惯而已. 这题关键点就是,如果a[i-1]<a[i]>a[i+1],显然3个分开(a[i]归左或右)不比在一起差. #include <cstdio> #include <cstring>

484D - Kindergarten DP

把每一段单调序列分成一组可以接近最优质. 然后在此基础上讨论这一段的单调序列的两个端点该分到哪个序列里面,记录一下最优值. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack&g

Codeforces Round #276 (Div. 1)D.Kindergarten DP贪心

D. Kindergarten In a kindergarten, the children are being divided into groups. The teacher put the children in a line and associated each child with his or her integer charisma value. Each child should go to exactly one group. Each group should be a

Codeforces 484(#276 Div 1) D Kindergarten DP

题意:给你一个数组,让你把连续的数分为一组,每一组的值为这一组数中的极差,问你这个怎样分组才能使得数组的极差和最大 解题思路: 可以分成 4种情况讨论 dp[i]  表示前 i+1项能得到的最大值 状态                                       状态转移方程 a[i-1] < a[i]  < a[i+1]        dp[i] = dp[i-1] + a[i+1] - a[i] a[i-1] > a[i]  < a[i+1]        dp

【codeforces 718E】E. Matvey&#39;s Birthday

题目大意&链接: http://codeforces.com/problemset/problem/718/E 给一个长为n(n<=100 000)的只包含‘a’~‘h’8个字符的字符串s.两个位置i,j(i!=j)存在一条边,当且仅当|i-j|==1或s[i]==s[j].求这个无向图的直径,以及直径数量. 题解:  命题1:任意位置之间距离不会大于15. 证明:对于任意两个位置i,j之间,其所经过每种字符不会超过2个(因为相同字符会连边),所以i,j经过节点至多为16,也就意味着边数至多

Codeforces 124A - The number of positions

题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't know exactly which position he occupies. He can say that there are no less than a people standing in front of him and no more than b people standing b

Codeforces 841D Leha and another game about graph - 差分

Leha plays a computer game, where is on each level is given a connected graph with n vertices and m edges. Graph can contain multiple edges, but can not contain self loops. Each vertex has an integer di, which can be equal to 0, 1 or  - 1. To pass th

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st