zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    MySQL大表优化方案
    写一个简单脚本检测mysql主从是否正常
    Nginx配置基于ip的虚拟主机
    推荐一些好的linux学习网站
    shell基础入门(一)
    centos7和linux防火墙配置入门
    centos7.0之vsftpd随笔
    获取系统相关属性
    linux 文件管理操作入门
    ANSI文件操作
  • 原文地址:https://www.cnblogs.com/baocong/p/7357276.html
Copyright © 2011-2022 走看看