zoukankan      html  css  js  c++  java
  • CF833B The Bakery

    题意

    将一个长度为(n)的序列分为(k)
    使得总价值最大
    一段区间的价值表示为区间内不同数字的个数
    (n<=35000,k<=50)

    Sol

    首先可以设状态(f[i][j])
    表示前(i)个数字分成(j)段的最大价值
    (f[i][j] = max){(f[l][j - 1] + Query(l + 1, i))}((0 <= l <= i - 1))
    (Query(l + 1, i))表示(l+1)(i)的不同数的个数

    然后
    你会发现
    (i)这个位置上的数上次的位置为(lst)
    则枚举到这个数字后,(lst)(i-1)这些(f)都要加(1)
    那么就可以枚举(k)
    然后每次重构线段树,把上一次分的(f)放进去
    查询+区间加法

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(4e4 + 5);
    
    IL int Input(){
    	RG int x = 0, z = 1; RG char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    int n, k, a[_], mx[_ << 2], tag[_ << 2], f[_], lst[_], id[_];
    
    IL void Build(RG int x, RG int l, RG int r){
    	tag[x] = 0;
    	if(l == r){
    		mx[x] = f[l];
    		return;
    	}
    	RG int mid = (l + r) >> 1;
    	Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r);
    	mx[x] = max(mx[x << 1], mx[x << 1 | 1]);
    }
    
    IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R){
    	if(L <= l && R >= r){
    		++mx[x], ++tag[x];
    		return;
    	}
    	RG int mid = (l + r) >> 1;
    	if(L <= mid) Modify(x << 1, l, mid, L, R);
    	if(R > mid) Modify(x << 1 | 1, mid + 1, r, L, R);
    	mx[x] = max(mx[x << 1], mx[x << 1 | 1]) + tag[x];
    }
    
    IL int Query(RG int x, RG int l, RG int r, RG int L, RG int R){
    	if(L <= l && R >= r) return mx[x];
    	RG int mid = (l + r) >> 1, ans = 0;
    	if(L <= mid) ans = Query(x << 1, l, mid, L, R);
    	if(R > mid) ans = max(ans, Query(x << 1 | 1, mid + 1, r, L, R));
    	return ans + tag[x];
    }
    
    int main(RG int argc, RG char *argv[]){
    	n = Input(), k = Input();
    	for(RG int i = 1; i <= n; ++i)
    		a[i] = Input(), lst[i] = id[a[i]], id[a[i]] = i;
    	for(RG int i = 1; i <= k; ++i){
    		Build(1, 0, n), Fill(f, 0);
    		for(RG int j = i; j <= n; ++j){
    			Modify(1, 0, n, lst[j], j - 1);
    			f[j] = Query(1, 0, n, 0, j - 1);
    		}
    	}
    	printf("%d
    ", f[n]);
    	return 0;
    }
    
    
  • 相关阅读:
    主机与虚拟机通信:以主机VS2010连接虚拟机MySql为例
    Json与类对象转换
    VS附加到进程调试的方法及应用场景
    地图API使用文档-以腾讯地图为例
    JS使用ActiveXObject读取数据库代码示例(只支持IE)
    css文件内引用外部资源文件的相对路径
    ::after,::before使用
    高德地图API应用
    LogNet4学习笔记
    MvcPager分页控件的使用
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8589720.html
Copyright © 2011-2022 走看看