• CF868 F. Yet Another Minimization Problem 决策单调优化 分治



    目录

    题目链接

    CF868F. Yet Another Minimization Problem

    题解

    (f_{i,j}=minlimits_{k=1}^{i}{f_{k,j-1}+w_{k,i}})
    (w_{l,r})为区间([l,r])的花费,1D1D的经典形式
    发现这个这是个具有决策单调性的转移
    单无法快速转移,我们考虑分治
    对于当前分治区间([l,r]) ,它的最优决策区间在([L,R])之间。
    对于([l,r])的中点(mid),我们可以暴力扫([L−mid])
    找到mid的最优决策点p。因为决策单调,所以([l,mid−1])最优决策区间为([L,p]),而([mid+1,r]),的最优决策区间在([p,R])
    分治下去
    求解区间:(|gets预处理 o | lfrac{qquadqquadqquaddownarrow^{mid}qquadqquadqquad}{}r)

    决策区间:(Lfrac{qquadqquadqquaddownarrow^{p}qquadqquadqquad}{}R)

    代码

    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    #define LL long long 
    #define gc getchar() 
    #define pc putchar
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = gc; 
    	while(c < '0' || c > '9' )c = gc; 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc; 
    	return x * f ;
    } 
    void print(LL x) {
    	 if(x >= 10) print(x / 10); 
    	 pc(x % 10 + '0'); 
    } 
    int n,K; 
    const int maxn = 200007; 
    int a[maxn],b[maxn],c[maxn]; 
    LL f[maxn],dp[maxn]; 
    void solve(int l,int r ,int L,int R,int w) {
    	if(l > r) return ; 
    	int mid = l + r >> 1,k = 0,p = std::min(mid,R); 
    	for(int i = l;i <= mid;++ i) w += c[a[i]] ++; 
    	for(int i = L;i <= p;++ i) { 
    		w -= -- c[a[i]]; 
    		if(dp[mid] > f[i] + w) dp[mid] = f[i] + w,k = i; 
    	} 
    	for(int i = L;i <= p;++ i) w += c[a[i]] ++; 
    	for(int i = l;i <= mid;++ i) w -= --c[a[i]]; 
    	solve(l,mid - 1,L,k,w); 
    	
    	for(int i = l;i <= mid;++ i) w += c[a[i]] ++; 
    	for(int i = L;i <  k;++ i) w -= -- c[a[i]]; 
    	solve(mid + 1,r,k,R,w); 
    	
    	
    	for(int i = L;i < k;++ i) ++ c[a[i]]; 
    	for(int i = l;i <= mid;++ i) -- c[a[i]]; 
    } 
    int main() { 
    	n = read(),K = read(); 
    	for(int i = 1;i <= n;++ i) 
    		f[i] = f[i - 1] + c[a[i] = read()] ++; 
    	memset(c,0,sizeof c); 
    	for(int i = 1;i <= K;++ i) { 
    		memset(dp,0x3f,sizeof dp); 
    		solve(1,n,1,n,0); 
    		std::swap(f,dp); 
    	} 
    	print(dp[n]); 
    	return 0; 	
    } 
    
  • 相关阅读:
    判断一个字符串之中出现次数最多的字符和它出现的次数
    冒泡排序
    vue 页面生成图片保存
    css实现0.5像素的底边框。
    web之面试常问问题:如何实现水平垂直居中?
    cocos 向左滚动公告
    SpringBoot 访问jsp文件报错Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/welcome.jsp]的解决办法
    vue 弹窗禁止底层滚动
    vue 倒计时 iOS无效
    axios之增删查改操作
  • 原文地址:https://www.cnblogs.com/sssy/p/9768594.html
Copyright © 2020-2023  润新知