Codeforces Round #426 (Div. 1) B. The Bakery DP+线段树

链接:

http://codeforces.com/contest/833/problem/B

题意:

给你n个数,分成k段,每段的值为其中不同的数的个数,求每段的值的和的最大值

题解:

显然需要用到动态规划。我们用dp[i][j]表示前j个数分成i段价值和的最大值。容易得到状态转移方程为

dp[i][j]=max{dp[i-1][x]+剩下数的贡献} {1<=x< j}

过程用线段树维护一下区间最大值即可。

代码:

 31 int n, k;
 32 int a[MAXN];
 33 int pos[MAXN], pre[MAXN];
 34 int Tree[MAXN << 2], Lazy[MAXN << 2];
 35 int dp[60][MAXN];
 36 
 37 void pushup(int rt) {
 38     Tree[rt] = max(Tree[rt << 1], Tree[rt << 1 | 1]);
 39 }
 40 
 41 void pushdown(int rt) {
 42     if (Lazy[rt]) {
 43         Tree[rt << 1] += Lazy[rt];
 44         Tree[rt << 1 | 1] += Lazy[rt];
 45         Lazy[rt << 1] += Lazy[rt];
 46         Lazy[rt << 1 | 1] += Lazy[rt];
 47         Lazy[rt] = 0;
 48     }
 49 }
 50 
 51 void build(int pos, int l, int r, int rt) {
 52     Lazy[rt] = 0;
 53     if (l == r) {
 54         Tree[rt] = dp[pos][l - 1];
 55         return;
 56     }
 57     int m = (l + r) >> 1;
 58     build(pos, lson);
 59     build(pos, rson);
 60     pushup(rt);
 61 }
 62 
 63 void update(int L, int R, int l, int r, int rt) {
 64     if (L <= l && r <= R) {
 65         Tree[rt]++;
 66         Lazy[rt]++;
 67         return;
 68     }
 69     pushdown(rt);
 70     int m = (l + r) >> 1;
 71     if (L <= m) update(L, R, lson);
 72     if (R > m) update(L, R, rson);
 73     pushup(rt);
 74 }
 75 
 76 int query(int L, int R, int l, int r, int rt) {
 77     if (L <= l && r <= R) return Tree[rt];
 78     pushdown(rt);
 79     int m = (l + r) >> 1;
 80     int ret = 0;
 81     if (L <= m) ret = max(ret, query(L, R, lson));
 82     if (R > m) ret = max(ret, query(L, R, rson));
 83     pushup(rt);
 84     return ret;
 85 }
 86 
 87 int main() {
 88     ios::sync_with_stdio(false), cin.tie(0);
 89     cin >> n >> k;
 90     rep(i, 1, n + 1) {
 91         cin >> a[i];
 92         pre[i] = pos[a[i]] + 1;
 93         pos[a[i]] = i;
 94     }
 95     rep(i, 1, k + 1) {
 96         build(i - 1, 1, n, 1);
 97         rep(j, 1, n + 1) {
 98             update(pre[j], j, 1, n, 1);
 99             dp[i][j] = query(1, j, 1, n, 1);
100         }
101     }
102     cout << dp[k][n] << endl;
103     return 0;
104 }

 

posted @ 2017-08-14 13:22  Flowersea  阅读(162)  评论(0编辑  收藏  举报