zoukankan      html  css  js  c++  java
  • [APIO2014]序列分割

    #include<bits/stdc++.h>
    #define RG register
    #define IL inline
    #define _ 150005
    #define eps 1e-7
    #define ll long long
    using namespace std; 
     
    ll n , K , s[_] , a[_] , C , inf , Res , L , R , hd , tl ;  
    struct Item{
        ll id , from , sum , v; 
        IL Item(){id = from = sum = v = 0 ; }  
    };
    Item operator + (const Item A , const Item B) {
        Item tmp ; tmp.id = A.id ; 
        tmp.from = B.id ; tmp.sum = B.sum + 1 ;
        tmp.v = B.v + s[B.id] * (s[A.id] - s[B.id]) + C ; 
        return tmp ; 
    }
    
    struct Solver{ 
        Item f[_] , que[_] ; ll ans[_] , tot ; ll Result ; 	
        IL double Slope(Item A , Item B){
            RG double Dy = (A.v - s[A.id]*s[A.id]) - (B.v - s[B.id]*s[B.id]) ; 
            RG double Dx = s[A.id] - s[B.id] ;  
            if(fabs(Dy) <= eps) return 0 ; 
            return 1.0 * Dy / Dx ; 
        }		
        IL ll solve(){
            hd = 1; tl = 1;  
            f[0].id = f[0].sum = f[0].from = f[0].v = 0 ;
            que[hd].id = que[hd].sum = que[hd].v = que[hd].from = 0 ; 
            for(RG int i = 1; i <= n; i ++){
                f[i].id = i ;
         		while(hd < tl && Slope(que[hd + 1] , que[hd]) >= -s[i]) ++ hd;
            	f[i] = f[i] + que[hd] ; 
                while(hd < tl && Slope(f[i] , que[tl - 1]) >= Slope(que[tl] , que[tl - 1])) -- tl; 
                que[++tl] = f[i] ;
            }
            return f[n].sum - 1 <= K;
        }
        
        IL void Get(){
            Result = f[n].v - (K + 1) * Res; 
            tot = 0 ; 
            for(RG int e = f[n].from; e ; e = f[e].from) ans[++tot] = e ;  		
        }
        IL void PutOut(){
            cout << Result << endl;
            for(RG int i = tot ; i >= 1 ; i --) cout << ans[i] << " " ;  
        }
    }E;
    
    int main(){
        std::ios::sync_with_stdio(false) ; 
        cin >> n >> K ;  
        for(RG int i = 1; i <= n; i ++) cin >> a[i] ; 
        for(RG int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i] ;
        inf = 1e15 ;  L = -inf ; R = inf ; Res = 0 ; 
        while(L <= R){
            C = (L + R) >> 1 ; 
            if(E.solve()) Res = C , E.Get() ,  L = C + 1 ; 
            else R = C - 1 ; 
        }
        E.PutOut() ; return 0 ; 
    } 
    
  • 相关阅读:
    Linux中rsync备份数据使用实例
    8个Date命令使用示例
    Linux中如何使用alias命令
    在LVM中恢复已删除的逻辑卷
    使用Dmidecode获取硬件信息使用实例
    Linux系统使用SSH登录之前如何显示横幅消息
    在Linux中修改打开文件数量限制的3种方法
    Linux中监控磁盘分区和使用情况的几个工具
    如何解决Ubuntu提示没有找到ifconfig命令
    Linux中ip命令的使用实例
  • 原文地址:https://www.cnblogs.com/Guess2/p/9051426.html
Copyright © 2011-2022 走看看