484D - Kindergarten DP

把每一段单调序列分成一组可以接近最优质。

然后在此基础上讨论这一段的单调序列的两个端点该分到哪个序列里面,记录一下最优值。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker,"/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007
#define mod 1000000007

/** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
    char c;
    while(!d);
    x=c-'0';
    while(d)p;
    return x;
}
template<class T> inline T& RDD(T &x)
{
    char c;
    while(g,c!='-'&&!isdigit(c));
    if (c=='-')
    {
        x='0'-g;
        while(d)n;
    }
    else
    {
        x=c-'0';
        while(d)p;
    }
    return x;
}
inline double& RF(double &x)      //scanf("%lf", &x);
{
    char c;
    while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.')
        {
            x=0;
            double l=1;
            while(d)nn;
            x*=l;
        }
        else
        {
            x='0'-c;
            while(d)n;
            if(c=='.')
            {
                double l=1;
                while(d)nn;
                x*=l;
            }
        }
    else if(c=='.')
    {
        x=0;
        double l=1;
        while(d)pp;
        x*=l;
    }
    else
    {
        x=c-'0';
        while(d)p;
        if(c=='.')
        {
            double l=1;
            while(d)pp;
            x*=l;
        }
    }
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;

int num[1000010];

int Judge(int x,int y)
{
    if(x == y)
        return 0;
    if(x < y)
        return -1;
    return 1;
}

_LL dp[2][1000010];

int main()
{
    int n,i,j;

    scanf("%d",&n);

    for(i = 1;i <= n; ++i)
        scanf("%d",&num[i]);

    int pre;

    memset(dp,0,sizeof(dp));

    for(num[n+1] = num[n],pre = 1,i = 2;i <= n; ++i)
    {
        if(Judge(num[pre],num[i])*Judge(num[i],num[i+1]) == -1 || i == n)
        {
            dp[0][i] = max(dp[1][pre] + abs(num[i]-num[pre]),dp[0][pre] + abs(num[pre+1]-num[i]));

            dp[1][i] = max(dp[0][pre],dp[1][pre]);

            dp[1][i] = max(dp[1][i],dp[1][pre]+abs(num[pre]-num[i-1]));

            if(pre+1 <= i-1)
                dp[1][i] = max(dp[1][i],dp[0][pre] + abs(num[pre+1]-num[i-1]));
            pre = i;
        }
    }

    printf("%I64d\n",max(dp[0][n],dp[1][n]));

    return 0;
}
时间: 2024-11-05 14:59:56

484D - Kindergarten DP的相关文章

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>

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 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  所以其他值都是没必要的  那么没有必要的值如果放在

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

poj 3692 Kindergarten (最大团模板题)

题目链接:http://poj.org/problem?id=3692 Kindergarten Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5156   Accepted: 2512 Description In a kindergarten, there are a lot of kids. All girls of the kids know each other and all boys also know e

poj3934Queue(dp)

题目链接: 啊哈哈,点我点我 题意: 有n个幼儿园的孩纸.然后从中找出m对孩子可以让他们看到两方,这样以便他们交流.. 思路: 首先能够考虑把n-1个人已经排成了m-2对.那么仅仅须要把这个最矮的随便插在队伍就能够凑成m对了.第二种情况是先排成m-1对.然后把最矮的那一个放在对首或者队尾.这样就到了状态转移方程. if(j>=2) dp[i][j]=dp[i-1][j-2]*(i-2) if(j>=1) dp[i][j]=dp[i][j]+dp[i-1][j-1]*2; 然后最開始把1个人2个

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往