1. 程式人生 > >CF868 F. Yet Another Minimization Problem 決策單調優化 分治

CF868 F. Yet Another Minimization Problem 決策單調優化 分治

efi getch 預處理 algo 單調性 代碼 arr 最優決策 ref

題目鏈接

CF868F. Yet Another Minimization Problem

題解

\(f_{i,j}=\min\limits_{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預處理\to | l\frac{\qquad\qquad\qquad\downarrow^{mid}\qquad\qquad\qquad}{}r\)

決策區間:\(L\frac{\qquad\qquad\qquad\downarrow^{p}\qquad\qquad\qquad}{}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;   
} 

CF868 F. Yet Another Minimization Problem 決策單調優化 分治