luogu P1725 琪露诺

二次联通门 : luogu P1725 琪露诺

/*
    luogu P1725 琪露诺 

    DP + 线段树 

    用线段树维护dp[i - R] ~ dp[i - L]的最大值

    然后 转移方程是
        dp[i] = max (dp[i - R], dp[i - R + 1], .... dp[i - L - 1], dp[i - L]) + number[i]

*/
#include <cstdio>

#define Max 200009
#define INF 1e7

inline int max (int a, int b)
{
    return a > b ? a : b;
}

void read (int &now)
{
    now = 0;
    bool flag = false;
    register char word = getchar ();
    while (word > ‘9‘ || word < ‘0‘)
    {
        if (word == ‘-‘)
            flag = true;
        word = getchar ();
    }
    while (word >= ‘0‘ && word <= ‘9‘)
    {
        now = now * 10 + word - ‘0‘;
        word = getchar ();
    }
    if (flag)
        now = -now;
}

int N, L, R;

int number[Max];

struct Segment
{
    struct Segment_Tree
    {
        int l;
        int r;
        int Maxn;
        int Mid;
    };

    Segment_Tree tree[Max << 3];

    void Build (int l, int r, int now)
    {
        tree[now].l = l;
        tree[now].r = r;
        if (l == r)
            return ;
        tree[now].Mid = (l + r) >> 1;
        Build (l, tree[now].Mid, now << 1);
        Build (tree[now].Mid + 1, r, now << 1 | 1);
    }

    int Query_Maxn (int l, int r, int now)
    {
        if (tree[now].l == l && tree[now].r == r)
            return tree[now].Maxn;
        if (r <= tree[now].Mid)
            return Query_Maxn (l, r, now << 1);
        else if (l > tree[now].Mid)
            return Query_Maxn (l, r, now << 1 | 1);
        else
            return max (Query_Maxn (l, tree[now].Mid, now << 1), Query_Maxn (tree[now].Mid + 1, r, now << 1 | 1));
    }

    void Change_Single (int pos, int now, int number)
    {
        if (tree[now].l == tree[now].r)
        {
            tree[now].Maxn = number;
            return ;
        }
        if (pos <= tree[now].Mid)
            Change_Single (pos, now << 1, number);
        else if (pos > tree[now].Mid)
            Change_Single (pos, now << 1 | 1, number);
        tree[now].Maxn = max (tree[now << 1].Maxn, tree[now << 1 | 1].Maxn);
    }
};

Segment Tree;

int main (int argc, char *argv[])
{
    read (N);
    read (L);
    read (R);
    Tree.Build (0, N, 1);
    for (int i = 0; i <= N; i++)
    {
        read (number[i]);
        if (i <= L)
            Tree.Change_Single (i, 1, number[i]);
    }
    for (int i = L + 1; i <= N; i++)
        if (i - L >= L)
            Tree.Change_Single (i, 1, Tree.Query_Maxn(max(L, i - R), i - L, 1) + number[i]);
        else
            Tree.Change_Single (i, 1, number[i]);
    printf ("%d", Tree.Query_Maxn (N - R, N, 1));
    return 0;
} 
时间: 2024-10-26 22:54:23

luogu P1725 琪露诺的相关文章

洛谷P1725 琪露诺 单调队列优化 DP

洛谷P1725 琪露诺 单调队列优化 DP 题意:1--n 每个点都有一个权值,从当前点i可以到达i+l--i+r 之间的点, 动态规划 方程 为 f[ i ] = max(f[ i ],f[ k ] ) +a[ i ] i-r<=k<=i-l 然而这样复杂度 就为 n^2 因为相当于 dp 是在求 一段区间的最大值,而这个最大值就可以用O(n) 来维护 注意 这个O(n) 是均摊O(n) 即将所有固定区间长度的 最大值求出来 是 O(n)的这样就把复杂度降到 O(n) 级别了 1 #incl

洛谷P1725 琪露诺

P1725 琪露诺 题目描述 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精.某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河岸去追青蛙.小河可以看作一列格子依次编号为0到N,琪露诺只能从编号小的格子移动到编号大的格子.而且琪露诺按照一种特殊的方式进行移动,当她在格子i时,她只会移动到i+L到i+R中的一格.你问为什么她这么移动,这还不简单,因为她是笨蛋啊.每一个格子都有一个冰冻指数A[i],编号为0的格子冰冻

洛谷—— P1725 琪露诺

https://www.luogu.org/problem/show?pid=1725 题目描述 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精.某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河岸去追青蛙.小河可以看作一列格子依次编号为0到N,琪露诺只能从编号小的格子移动到编号大的格子.而且琪露诺按照一种特殊的方式进行移动,当她在格子i时,她只会移动到i+L到i+R中的一格.你问为什么她这么移动,这还不简单,因

P1725 琪露诺

题目描述 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河岸去追青蛙. 小河可以看作一列格子依次编号为0到N,琪露诺只能从编号小的格子移动到编号大的格子.而且琪露诺按照一种特殊的方式进行移动,当她在格子i时,她只移动到区间[i+l,i+r]中的任意一格.你问为什么她这么移动,这还不简单,因为她是笨蛋啊. 每一个格子都有一个冰冻指数A[i],编号为0的格子冰冻指数

codevs 3943 数学奇才琪露诺

二次联通门 : codevs 3943 数学奇才琪露诺 /* codevs 3943 数学奇才琪露诺 一眼看过去 感觉这道题是个神题...不可做 后来打了个暴力, 0分 再后来仔细想了想 既然L,R<=10^9 那么数位之和最大就到81 (999999999) 那么直接枚举数位和来分解就好了... */ #include <cstdio> #define Limit 81 void read (int &now) { register char word = getchar ()

琪露诺

传送门啦 本人第一个单调队列优化 $ dp $,不鼓励鼓励? 琪露诺这个题,$ dp $ 还是挺好想的对不,但是暴力 $ dp $ 的话会 $ TLE $ ,所以我们考虑用单调队列优化. 原题中说她只移动到区间 $ [i+L,i+R] $ 中的任意一格,所以我们单调队列在转移的时候 $ push $ 的应该是 $ dp[i-L] $ ,而不是 $ dp[i] $ ,对于每一段区间,我们用起点(队头)来更新答案就好了. 最后一步,因为区间的限制,我们只用在 $ [n-R+1,n] $ 中找一个最大

题解 P1725 【琪露诺】

可以非常简单地推出转移方程式: f[i]= max(f[i-r,i-r])+a[i] 然后 不用脑子地 用常规思路敲出来: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MARX=0xf; int n,l,r,ans; int a[300010]; int f[300010]; int main() { memset(f,-MARX,sizeof

题解:琪露诺的冰雪小屋luogu3693

庆祝通过noip2018初赛,系列五题EP1. 题目描述: https://www.luogu.org/problemnew/show/P3693 调试记录:  真的很爽 下面是代码: 目前写过的最长的代码 1#include<bits/stdc++.h> 2#define N 21  3#define map ___map 4using namespace std; 5int n,m,cnt_block,R,C,D,S,HR,HC,HX,HY,HM,H,not_outside,maxhigh

luogu P1282 多米诺骨牌

题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9,S2=1+5+3+2=11,|S1-S2|=2.每个多米诺骨牌可以旋转180°,使得上下两个方块互换位置. 编程用最少的旋转次数使多米诺骨牌上下2行点数之差达到最小. 对于图中的例子,只要将最后一个多米诺骨牌旋转180°,可使上下2行点数之差为0. 输入输出格式 输入格式: 输入文件的第一行是一个正