zoukankan      html  css  js  c++  java
  • CF 833 B. The Bakery

    B. The Bakery

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

    题意:

      将一个长度为n的序列分成k份,每份的cost为不同的数的个数,求最大cost的和。1≤n≤35000,1≤k≤50

    分析:

      dp[i][j]表示前i个数,分了j份。dp[i][k]=dp[j][k-1]+cost(j+1,i);cost(j+1,i)为这一段中不同数的个数。

      然后考虑如何优化。发现每次增加一个位置,pre[i]~i-1区间的每个转移的位置的cost+1。然后每次转移是在上一个dp数组中取最大值,于是线段树维护。

    代码:

     1 /*
     2 * @Author: mjt
     3 * @Date:   2018-10-15 14:52:11
     4 * @Last Modified by:   mjt
     5 * @Last Modified time: 2018-10-15 15:27:53
     6 */
     7 #include<cstdio>
     8 #include<algorithm>
     9 #include<cstring>
    10 #include<cmath>
    11 #include<iostream>
    12 #include<cctype>
    13 #include<set>
    14 #include<vector>
    15 #include<queue>
    16 #include<map>
    17 #define fi(s) freopen(s,"r",stdin);
    18 #define fo(s) freopen(s,"w",stdout);
    19 using namespace std;
    20 typedef long long LL;
    21 
    22 inline int read() {
    23     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    24     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    25 }
    26 
    27 const int N = 35005;
    28 
    29 int dp[N][55], pre[N], last[N], a[N];
    30 int n, k;
    31 
    32 #define Root 1, n, 1
    33 #define lson l, mid, rt << 1
    34 #define rson mid + 1, r, rt << 1 | 1
    35 struct SegmentTree {
    36     int mx[N << 2], tag[N << 2], Cur;
    37     inline void pushup(int rt) { mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); }
    38     inline void pushdown(int rt) {
    39         if (tag[rt]) {
    40             tag[rt << 1] += tag[rt]; mx[rt << 1] += tag[rt];
    41             tag[rt << 1 | 1] += tag[rt]; mx[rt << 1 | 1] += tag[rt];
    42             tag[rt] = 0;
    43         }
    44     }
    45     void build(int l,int r,int rt) {
    46         tag[rt] = 0;
    47         if (l == r) {
    48             mx[rt] = dp[l][Cur]; return ;
    49         }
    50         int mid = (l + r) >> 1;
    51         build(lson); build(rson);
    52         pushup(rt);
    53     }
    54     void update(int l,int r,int rt,int L,int R) {
    55         if (L <= l && r <= R) {
    56             mx[rt] ++; tag[rt] ++;
    57             return ;
    58         }
    59         pushdown(rt);
    60         int mid = (l + r) >> 1;
    61         if (L <= mid) update(lson, L, R);
    62         if (R > mid) update(rson, L, R);
    63         pushup(rt);
    64     }
    65     int query(int l,int r,int rt,int L,int R) {
    66         if (L <= l && r <= R) {
    67             return mx[rt];
    68         }
    69         pushdown(rt);
    70         int mid = (l + r) >> 1, res = 0;
    71         if (L <= mid) res = max(res, query(lson, L, R));
    72         if (R > mid) res = max(res, query(rson, L, R));
    73         return res;
    74     }
    75 }T;
    76 
    77 void solve(int now) {
    78     T.Cur = now - 1; T.build(Root);
    79     for (int i=now; i<=n; ++i) {
    80         T.update(Root, pre[i], i - 1); // 线段树维护的是dp[j][now-1]+cost(j+1,i)的值,所以pre[i]~i-1这个区间加1!!!
    81         dp[i][now] = T.query(Root, 1, i - 1);
    82     }
    83 }
    84 
    85 int main() { 
    86     n = read(), k = read();
    87     for (int cnt=0,i=1; i<=n; ++i) {
    88         a[i] = read();
    89         pre[i] = last[a[i]]; last[a[i]] = i;
    90         if (pre[i] == 0) cnt ++;
    91         dp[i][1] = cnt;
    92     }
    93     for (int i=2; i<=k; ++i) solve(i);
    94     cout << dp[n][k];
    95     return 0;
    96 }
  • 相关阅读:
    vue3.0配置代理proxy 解决跨域问题
    1/26 机器人未来待解决问题
    每日一诵
    2020/11/14 关于股票的价格
    2020/11/14 再思股票价值
    11/2 股票价值
    我们为什么会越来越笨
    关于追女朋友
    关于早睡早起
    vue学习心得
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9791293.html
Copyright © 2011-2022 走看看