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

Posted dream-maker-yk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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<bits/stdc++.h>
using namespace std;
//----------------------------------------------
typedef pair<int, int> pi;
typedef long long ll;
typedef double db;
#define fi first
#define se second
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
void Read(T &x) {
  bool w = 1;x = 0;
  char c = getchar();
  while (!isdigit(c) && c != '-') c = getchar();
  if (c == '-') w = 0, c = getchar();
  while (isdigit(c)) {
    x = (x<<1) + (x<<3) + c -'0';
    c = getchar();
  }
  if (!w) x = -x;
}
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e5 + 10;
const int M = 23;
int n, m, a[N], cnt[N] = {0};
ll nowl = 1, nowr = 0, res = 0;
ll dp[N][M];
void move_step(int al, int ar) {
  while (nowr < ar) {
    ++nowr;
    res += cnt[a[nowr]];
    ++cnt[a[nowr]];
  }
  while (nowl > al) {
    --nowl;
    res += cnt[a[nowl]];
    ++cnt[a[nowl]];
  }
  while (nowr > ar) {
    --cnt[a[nowr]];
    res -= cnt[a[nowr]];
    --nowr;
  }
  while (nowl < al) {
    --cnt[a[nowl]];
    res -= cnt[a[nowl]];
    ++nowl;
  }
}
void solve(int l, int r, int ql, int qr, int k) {
  if (l > r) return;
  int mid = (l + r) >> 1, pos = mid;
  fu(i, ql, min(qr, mid - 1)) {
    move_step(i + 1, mid);
    if (dp[i][k - 1] + res < dp[mid][k]) {
      dp[mid][k] = dp[i][k - 1] + res;
      pos = i;
    }
  }
  solve(l, mid - 1, ql, pos, k);
  solve(mid + 1, r, pos, qr, k);
}
int main() {
#ifdef dream_maker
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#endif
  Read(n), Read(m);
  fu(i, 1, n) Read(a[i]);
  fu(i, 1, n) 
    fu(j, 0, m) dp[i][j] = INF_of_ll;
  dp[0][0] = 0;
  fu(i, 1, m) solve(1, n, 0, n, i);
  Write(dp[n][m]);
  return 0;
}

以上是关于Codeforces 868F. Yet Another Minimization Problem决策单调性优化DP分治莫队的主要内容,如果未能解决你的问题,请参考以下文章

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

CodeForces - 868F Yet Another Minimization Problem

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

cf868F. Yet Another Minimization Problem(决策单调性 分治dp)

[CF868F] Yet Another Minimization Problem

CF868 F. Yet Another Minimization Problem 决策单调优化 分治