CodeForces 834D 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 }