CodeForces 834D The Bakery

The Bakery

题意:将N个数分成K块, 每块的价值为不同数字的个数, 现在求总价值最大。

题解:dp[i][j] 表示 长度为j 且分成 i 块的价值总和。 那么 dp[i][j] = max(dp[i-1][x]+右边的数的贡献) ( 1<=x < j )。 如果每次都从左到右for过去一定会TLE, 所以我们用线段树来优化这个查询的过程, 并且用滚动数组消去第二维空间。

每次新扫到一个数T, 他就会在上一个T的位置+1 --- 现在这个T的位置产生数目加一的贡献。

然后每次扫完一次, 都用DP的值去重新建树。并且将DP的对应位置往右移动一位, 这样下次访问这个位置就是  dp[i-1][x-1] + dp[1][x-j]的价值了。 (j 为现在的位置)。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned LL
 5 #define fi first
 6 #define se second
 7 #define lson l,m,rt<<1
 8 #define rson m+1,r,rt<<1|1
 9 #define max3(a,b,c) max(a,max(b,c))
10 const int INF = 0x3f3f3f3f;
11 const LL mod = 1e9+7;
12 typedef pair<int,int> pll;
13 const int N = 35010;
14 int dp[N], tree[N<<2], lazy[N<<2], pos[N], last[N];
15 void Push_Up(int rt){
16     tree[rt] = max(tree[rt<<1], tree[rt<<1|1]);
17 }
18 void Push_Down(int rt){
19     if(lazy[rt]){
20         lazy[rt<<1]+=lazy[rt];
21         lazy[rt<<1|1]+=lazy[rt];
22         tree[rt<<1]+=lazy[rt];
23         tree[rt<<1|1]+=lazy[rt];
24         lazy[rt] = 0;
25     }
26 }
27 void Build(int l, int r, int rt){
28     lazy[rt] = 0;
29     if(l == r){
30         tree[rt] = dp[l-1];
31         return ;
32     }
33     int m = l+r >> 1;
34     Build(lson);
35     Build(rson);
36     Push_Up(rt);
37 }
38 void Update(int L, int R, int l, int r, int rt){
39     if(L <= l && r <= R){
40         lazy[rt]++;
41         tree[rt]++;
42         return;
43     }
44     int m = l+r >> 1;
45     Push_Down(rt);
46     if(L <= m) Update(L,R,lson);
47     if(m < R) Update(L,R,rson);
48     Push_Up(rt);
49 }
50 int Query(int L, int R, int l, int r, int rt){
51     if(L <= l && r <= R) return tree[rt];
52     int ans = 0;
53     int m = l+r >> 1;
54     Push_Down(rt);
55     if(L <= m) ans = max(ans, Query(L,R,lson));
56     if(m < R) ans = max(ans, Query(L,R,rson));
57     return ans;
58 }
59 int main(){
60     memset(pos, 0, sizeof(pos));
61     memset(last, 0, sizeof(last));
62     int n, k, t;
63     scanf("%d%d",&n,&k);
64     for(int i = 1; i <= n; i++){
65         scanf("%d",&t);
66         last[i] = pos[t] + 1;
67         pos[t] = i;
68     }
69     for(int i = 1; i <= k; i++){
70         Build(1,n,1);
71         for(int j = 1; j <= n; j++){
72             Update(last[j],j,1,n,1);
73             dp[j] = Query(1,j,1,n,1);
74         }
75     }
76     printf("%d\n", dp[n]);
77     return 0;
78 }
View Code

 

posted @ 2018-03-03 20:16  Schenker  阅读(140)  评论(0编辑  收藏  举报