题解CF#426(Div. 1) B.The Bakery
Posted twilight-sx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解CF#426(Div. 1) B.The Bakery相关的知识,希望对你有一定的参考价值。
一个非常明显的 (nk) dp 状态 (f[i][k]) 表示以 (i) 为第 (k) 段的最后一个元素时所能获得的最大代价。转移的时候枚举上一段的最后一个元素 (j)更新状态即可。考虑如何优化这个过程?主要的时间消耗在两个部分:一个是确定一段区间的贡献,另一个是找到最大的值。
这两个都是可以使用线段树来维护的,一段区间的贡献我们可以扫描线,而最大值则直接线段树维护最大值。如何滚动反而好像是最难的……想了一会儿,因为显然 memset 不可接受,然而我们可以 (O(n)) 建树啊……简直对自己的zz无语惹~
#include <bits/stdc++.h> using namespace std; #define maxn 2000000 #define maxm 40000 int n, K, ans, a[maxn], rec[maxn], last[maxn]; int f[maxm][55]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x * k; } struct Segament_Tree { int mx[maxn], mark[maxn]; void Push_Down(int p) { mark[p << 1] += mark[p], mark[p << 1 | 1] += mark[p]; mx[p << 1] += mark[p], mx[p << 1 | 1] += mark[p]; mark[p] = 0; } void Build(int p, int l, int r, int K) { if(l == r) { mark[p] = 0, mx[p] = f[l - 1][K]; return; } int mid = (l + r) >> 1; mark[p] = 0; Build(p << 1, l, mid, K), Build(p << 1 | 1, mid + 1, r, K); mx[p] = max(mx[p << 1], mx[p << 1 | 1]); } void Update(int p, int l, int r, int L, int R, int x) { if(L <= l && R >= r) { mx[p] += x, mark[p] += x; return; } if(L > r || R < l) return; int mid = (l + r) >> 1; Push_Down(p); Update(p << 1, l, mid, L, R, x); Update(p << 1 | 1, mid + 1, r, L, R, x); mx[p] = max(mx[p << 1], mx[p << 1 | 1]); } int Query(int p, int l, int r, int L, int R) { if(L <= l && R >= r) { return mx[p]; } if(L > r || R < l) return 0; int mid = (l + r) >> 1; Push_Down(p); return max(Query(p << 1, l, mid, L, R), Query(p << 1 | 1, mid + 1, r, L, R)); } }T[2]; int main() { n = read(), K = read(); for(int i = 1; i <= n; i ++) { a[i] = read(); last[i] = rec[a[i]], rec[a[i]] = i; } int now = 1, pre = 0; for(int j = 1; j <= K; j ++) { for(int i = 1; i <= n; i ++) { T[pre].Update(1, 1, n, last[i] + 1, i, 1); f[i][j] = T[pre].Query(1, 1, n, 1, i); } T[now].Build(1, 1, n, j); swap(now, pre); } printf("%d ", f[n][K]); return 0; }
以上是关于题解CF#426(Div. 1) B.The Bakery的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 108 (Rated for Div. 2)-B. The Cake Is a Lie-题解
题解——CF Manthan, Codefest 18 (rated, Div. 1 + Div. 2) T5(思维)
CF1083(Round #526 Div. 1) 简要题解
codeforces比赛题解#868 CF Round #438 (Div.1+Div.2)