首页 > 其他分享 >题解:P10977 Cut the Sequence

题解:P10977 Cut the Sequence

时间:2024-10-22 20:42:46浏览次数:7  
标签:状态 Cut int 题解 mid leq P10977 max 转移

题目传送门

分析

看到这种题就可以想到动态规划,先设状态:$f_i$ 表示考虑前 $i$ 个数,所需要的最小代价。

发现 $f_i$ 可以从所有 $i$ 以前的状态加后一段区间转移过来,于是可以列出状态转移方程:

$$f_i = \min_{j = i - 1}^{s_i - s_j \leq m}(f_j + \max_{k = j + 1}^i)$$

其中 $j$ 是上一个区间的右端点,$s$ 数组为前缀和数组。

不难发现每次转移 $f_i$ 的复杂度是 $O(N)$ 的,总复杂度为 $O(N^2)$,无法通过此题。

考虑将 $f_i$ 的转移过程进行优化。

由题目的性质,可以发现 $f_i$ 有单调不降的性质,基于这一点,我们可以在转移时:

如果 $a_j \leq a_{j+1}$。

则 $\max_{k = j}^i = \max_{k = j + 1}^i$。

则 $f_{j-1} + \max_{k = j}^i \leq f_j + \max_{k = j + 1}^i$。

基于这一点,可以转移过来的状态就可以用单调队列来存储了,并且用 multiset 来确定最优状态。

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define N 100010
int n, m, a[N], s[N], f[N], l, r, q[N << 2];
multiset<int> S;
signed main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] > m) //如果有大于m的数,肯定无解,直接输出-1。
        {
            cout << -1;
            return 0;
        }
        s[i] = s[i - 1] + a[i];
    }
    l = 1;
    r = 0;
    for (int i = 1; i <= n; i++)
    {
        while (l <= r && s[i] - s[q[l]] > m) //如果当前区间和大于m,直接舍去。
        {
            S.erase(f[q[l]] + a[q[l + 1]]); //这里要加的是a[q[l+1]],因为这是当前区间的最大值。
            l++;
        }
        while (l <= r && a[q[r]] < a[i]) //如果前面的数比当前数小,就会算错当前区间最大值,所以这里要提前弹出这些数。
        {
            S.erase(f[q[r - 1]] + a[q[r]]);
            r--;
        }
        if (l <= r) //如果弹完后,单调队列中还有元素,就可以加入以当前值作为最大值的答案。
        {
            S.insert(f[q[r]] + a[i]);
        }
        q[++r] = i;
        int L = 0, R = i - 1, c;
        while (L <= R) //这里求出距当前位置最远的区间左端点使区间的和小于等于m,为的是避免S中没有元素导致无法更新答案。
        {
            int mid = (L + R) >> 1;
            if (s[i] - s[mid] > m)
            {
                L = mid + 1;
            }
            else
            {
                c = mid;
                R = mid - 1;
            }
        }
        f[i] = f[c] + a[q[l]]; //这种情况下的最大值为a[q[l]]。
        if (S.size())
        {
            f[i] = min(f[i], *S.begin()); //如果S中有元素,就用S中最小的元素更新答案。
        }
    }
    cout << f[n];
}

标签:状态,Cut,int,题解,mid,leq,P10977,max,转移
From: https://www.cnblogs.com/awmmmmmm/p/18493705

相关文章

  • [题解]P2671 [NOIP2015 普及组] 求和
    P2671[NOIP2015普及组]求和可以发现我们对相同颜色且编号奇偶性相同的元素归为一组,组内的元素两两都满足题目条件,且这样可以不重不漏覆盖所有答案。设分完组之后,某一组内的元素编号分别是\(a_1,a_2,\dots,a_q\),数字分别是\(b_1,b_2,\dots,b_q\),则根据题意,该组的答案是:\[\lar......
  • 20241021 校测T1 致敬传奇捆绑测试题目(Perm) 题解
    题解:致敬传奇捆绑测试题目Perm来自不知道什么时候的回忆。给定正整数\(n\),一个\(1\simn\)的排列\(p\)是一个好排列,当且仅当使得对于任意\(1\lek<n\),都有\(\sum_{i=1}^kp_i>p_{k+1}\)。现在请你求出字典序第小的好排列\(p\)。\(1\len\le10^6\),\(1\lek\le......
  • [ARC133E] Cyclic Medians 题解
    一点不会套路。思路对于中位数相关,发现我们不好直接表示与中位数有关的内容。不妨枚举\(x\),把大于\(x\)的标为\(1\),小于等于\(x\)的标为\(0\),这样把所有最终为一的方案数加起来就是原来的答案。大概是这样一个东西:\[k=\sum_{i=0}^k[i<k]\]这个怎么求呢。发现若一组......
  • Public NOIP Round #7 T3 黑白棋子 题解
    Description有一棵\(n\)个点的树,顶点的编号为\(1\)到\(n\)。对于树中的每个顶点,可能存在一个白色的棋子、一个黑色的棋子,或者没有棋子。树上正好有\(w\)个白色棋子和\(b\)个黑色棋子。另外,对于每一对具有相同颜色棋子的顶点,存在一条路径,路径上的每个顶点都包含相同颜色......
  • AT_agc064_c [AGC064C] Erase and Divide Game 题解
    先考虑所有\(l_i=r_i\)时怎么做,可以建出反向Trie树,问题转化为从根开始每次向左子树或右子树走,第一个拿到空子树的人输,直接在Trie上dp即可。考虑从叶子层开始对每一层的点合并两个子树的dp值,发现每一层值相同的连续段是较少的。于是可以维护这些连续段,每次合并要将每个......
  • 洛谷P2596 [ZJOI2006] 书架 题解 splay tree 模板题
    题目链接:https://www.luogu.com.cn/problem/P2596主要涉及的操作就是:找到某一个编号的点(这个操作可以不用splaytree维护)删除某个点将某一个点插入到最前面,最后面,或者某一个位置查询前序遍历为\(k\)的节点编号因为每次删除都会又把这个点加回去,所以可以复用\(n\)个......
  • [题解]CF825E Minimal Labels
    LPhang为什么是神?思路显然可以想到一个错误的贪心:直接拓扑排序,每一次选择当前可以拓展的点中最小的元素进行编号。由于可能存在一个值较小的元素被藏在一个较大的元素后面,这种贪心就会出问题。出问题的本质原因就是我们希望字典序最小,就得使得越小的位置分配到更小的值。不妨......
  • 历年CSP-J初赛真题解析 | 2017年CSP-J初赛完善程序(27-36)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客(快速幂)请完善下面的程序,该程序使用分治法求x......
  • CF2023D Many Games 题解
    赛时被创四了。思路考虑我们什么时候合并会比原来优。例如,我们现在要合并\(p_1,w_1\)和\(p_2,w_2\),同时保证,\(w_1\gew_2\)。那么有:\[\frac{p_1}{100}\timesw_1\le\frac{p_1}{100}\times\frac{p_2}{100}\times(w_1+w_2)\]\[\frac{p_2}{100}\timesw_2\le\frac{p_1}{......
  • 01 Eclipse使用Maven慢的问题解决
    1.Eclipse使用的是内置的MavenEclipse有可能使用了内置的Maven,而不是独立安装的Maven。如果使用Eclipse内置的Maven,默认的settings.xml可能并未生成。你可以按以下步骤检查或修改Maven设置路径:a.检查Eclipse使用的Maven配置点击Window->Preferences在......