CodeForces - 868F Yet Another Minimization Problem

Description

给定一个长度为 \(n(n\le 10^5)\) 的数列,第 \(i\) 个数是 \(a_i\in[1,n]\) ,要求将其划分为 \(k(2\le k\le min(20,n))\) 段以后每段价值和最小。

定义一段的价值为该段相同数的数对个数。

Solution

定义 \(calc(l,r)\) 为 \([l,r]\) 这一段的价值, \(dp[j][i]\) 为前 \(i\) 个数划分为 \(j\) 段的最小价值。那么显然有

\[
dp[j][i]=min\{dp[j-1][i']+calc(i'+1,i),i'<i\}
\]

因为 \(dp[j][i]\) 仅由 \(dp[j-1][i']\) 转移来,不妨设 \(j\) 固定。

令 \(f(i)\) 表示 \(i\) 对应的最优决策点 \(i'\) 。打表不难发现 \(f(i)\) 单调递增。

考虑分治。\(solve(l,r,L,R)\) 表示对于 \(i\in [l,r]\) ,有 \(f(i)\in {L,R}\) 。枚举出 \(mid=\cfrac{l+r}{2}\) 的决策点 \(f(mid)\) 后分治 \(solve(l,mid-1,L,f(mid))\) ,\(solve(mid+1,r,f(mid),R)\) 即可。

对于 \(calc(l,r)\) ,因为 \(l\) 和 \(r\) 的每次移动后都可以 \(O(1)\) 计算答案,所以可以莫队。

#include<bits/stdc++.h>
using namespace std;

template <class T> inline void read(T &x) {
    x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
    for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
}

#define N 100001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define ll long long

const ll INF = 0x3f3f3f3f3f3f3f3f, P = 1e9 + 7;
int n, K, a[N], now, nxt = 1, lf = 1, ri, cnt[N];
ll dp[2][N], sum;

inline void calc(int l, int r) {
    while (ri < r) sum += cnt[a[++ri]], cnt[a[ri]]++;
    while (ri > r) cnt[a[ri]]--, sum -= cnt[a[ri--]];
    while (lf > l) sum += cnt[a[--lf]], cnt[a[lf]]++;
    while (lf < l) cnt[a[lf]]--, sum -= cnt[a[lf++]];
}

#define mid (l + r >> 1)
void solve(int l, int r, int L, int R) {
    if (l > r) return;
    dp[nxt][mid] = INF;
    int t;
    rep(i, L, min(mid, R)) {
        calc(i, mid);
        if (dp[nxt][mid] > dp[now][i - 1] + sum) dp[nxt][mid] = dp[now][i - 1] + sum, t = i;
    }
    solve(l, mid - 1, L, t), solve(mid + 1, r, t, R);
}

int main() {
    read(n), read(K);
    rep(i, 1, n) read(a[i]);
    memset(dp, INF, sizeof dp); dp[now][0] = 0;
    while (K--) solve(1, n, 1, n), swap(now, nxt);
    printf("%lld", dp[now][n]);
    return 0;
}

原文地址:https://www.cnblogs.com/aziint/p/9189225.html

时间: 2024-08-03 04:14:30

CodeForces - 868F Yet Another Minimization Problem的相关文章

Codeforces 868F. Yet Another Minimization Problem【决策单调性优化DP】【分治】【莫队】

LINK 题目大意 给你一个序列分成k段 每一段的代价是满足\((a_i=a_j)\)的无序数对\((i,j)\)的个数 求最小的代价 思路 首先有一个暴力dp的思路是\(dp_{i,k}=min(dp_{j,k}+calc(j+1,i))\) 然后看看怎么优化 证明一下这个DP的决策单调性: trz说可以冥想一下是对的就可以 所以我就不证了 (其实就是决策点向左移动一定不会更优) 然后就分治记录当前的处理区间和决策区间就可以啦 //Author: dream_maker #include<bi

CodeForces 868F Yet Another Minimization Problem(决策单调性优化 + 分治)

题意 给定一个序列 \(\{a_1, a_2, \cdots, a_n\}\),要把它分成恰好 \(k\) 个连续子序列. 每个连续子序列的费用是其中相同元素的对数,求所有划分中的费用之和的最小值. \(2 \le n \le 10^5, 2 \le k \le \min(n, 20), 1 \le a_i \le n\) 题解 \(k\) 比较小,可以先考虑一个暴力 \(dp\) . 令 \(dp_{k, i}\) 为前 \(i\) 个数划分成 \(k\) 段所需要的最小花费. 那么转移如下

【CodeForces】868F. Yet Another Minimization Problem

原题链接 题目大意是有N个数,分成K段,每一段的花费是这个数里相同的数的数对个数,要求花费最小 如果只是区间里相同数对个数的话,莫队就够了 而这里是!边单调性优化边莫队(只是类似莫队)!而移动的次数和分治的复杂度是一样的! 这个时候就不能用单调栈+二分了,得用分治 分治的方法就是\(Solve(l,r,ql,qr)\)表示我想计算区间\([l,r]\)的答案,然后转移过来的区间在\([ql,qr]\) 暴力计算出\(f[mid]\)的值,找到最优转移点是\(k\),然后分成\(Solve(l,m

Codeforces Round #253 (Div. 2), problem: (B)【字符串匹配】

简易字符串匹配,题意不难 1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int main(){ 9 int i, j, k, t, n; 10 int num, flag, ans; 11 char a[300]; 12 sc

codeforces#253 D - Andrey and Problem里的数学知识

这道题是这样的,给主人公一堆事件的成功概率,他只想恰好成功一件. 于是,问题来了,他要选择哪些事件去做,才能使他的想法实现的概率最大. 我的第一个想法是枚举,枚举的话我想到用dfs,可是觉得太麻烦. 于是想是不是有什么规律,于是推导了一下,推了一个出来,写成代码提交之后发现是错的. 最后就没办法了,剩下的时间不够写dfs,于是就放弃了. 今天看thnkndblv的代码,代码很短,于是就想肯定是有什么数学规律,于是看了一下, 果然如此. 是这样的,还是枚举,当然是有技巧的,看我娓娓道来. 枚举的话

Codeforces Round #438 by Sberbank and Barcelona Bootcamp (Div. 1 + Div. 2 combined) F. Yet Another Minimization Problem

$f[i][k]$ 表示前 $i$ 个分成 $k$ 段,且最后一段以 $i$ 结尾的最小值 容易写出转移方程 $f[i][k] = \min \{f[j][k - 1] + calc(j+1,i)\}$ 因为具有决策单调性(打表 or 证明(不会)),就可以一种分治算法来优化 具体实现就是 $solve(l,r,L,R)$ 表示要求出 $(l,r)$ 之间的 dp 值,而决策点能取的区间为 $[L,R]$ 先暴力求出 $mid=\dfrac{l+r}{2}$ 的决策点 $pos$,再调用 $so

Codeforces Round #427 (Div. 2) Problem C Star sky (Codeforces 835C) - 前缀和

The Cartesian coordinate system is set in the sky. There you can see n stars, the i-th has coordinates (xi, yi), a maximum brightness c, equal for all stars, and an initial brightness si (0 ≤ si ≤ c). Over time the stars twinkle. At moment 0 the i-th

Codeforces 776D:The Door Problem(DFS染色)

http://codeforces.com/problemset/problem/776/D 题意:有n个门,m个开关,每个门有一个当前的状态(0表示关闭,1表示打开),每个开关控制k个门,但是每个门确切的受两个开关控制,如果一个开关打开,那么原来关闭的门会打开,打开的门关闭,问是否存在一个情况使得所有的门打开. 思路:类似于01染色,把开关当成点,门当前的状态当成边权建图.初始先假设一个门的状态(初始假设为0和假设为1都是一样的,举几个例子就发现了),然后因为每个门受两个开关控制,所以可以推出

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h