zoukankan      html  css  js  c++  java
  • 序列分割「APIO 2014」

    题意

    给定一个序列,进行(k)次操作,每次操作将会分割序列。

    对于每次操作,可以选择将任意一个区间在任意点分割开,得到左侧和乘以右侧和的收益。

    求收益最大值。


    思路

    子状态(f[i][k])表示前(i)个数割(k)次最大收益。

    推出方程为(f[i][k]=max(f[j][k-1]+sum[j]*(sum[i]-sum[j])))

    滚动一下可以去掉一维。

    假设有决策点(x,y)(x)优于(y),那么可以化简得到(frac{f[x]-sum[x]^2-f[y]+sum[y]^2}{sum[y]-sum[x]}>sum[i])。斜率优化套一下即可。

    //注意本题会有(sum[x]==sum[y])的情况

    (end)

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	#define int long long
    	
    	const int N=100010;
    	
    	int n,k;
    	int head,tail;
    	int sum[N],dp[N],dp2[N],queue[N];//,pre[N][205];
    	
    	inline double slope (int x,int y) {
    		if (sum[x]==sum[y]) return -1e18;
    		return (double)(dp2[x]-sum[x]*sum[x]-dp2[y]+sum[y]*sum[y])/(double)(sum[y]-sum[x]);
    	}
    
    	inline void MAIN () {
    		read(n),read(k);
    		for (register int i=1; i<=n; ++i) {
    			read(sum[i]),sum[i]+=sum[i-1];
    		}
    		for (register int t=1; t<=k; ++t) {
    			head=tail=1,queue[head]=0;
    			for (register int i=1; i<=n; ++i) {
    				while (head<tail&&slope(queue[head],queue[head+1])<=sum[i]) ++head;
    				dp[i]=dp2[queue[head]]+sum[queue[head]]*(sum[i]-sum[queue[head]]);
    //				pre[i][t]=queue[head];
    				while (head<tail&&slope(queue[tail-1],queue[tail])>=slope(queue[tail],i)) --tail;
    				queue[++tail]=i;	
    			}
    			memcpy(dp2,dp,sizeof(dp));	
    		}
    		write(dp[n]),putchar('
    ');
    //		for (register int x=n,i=k; i>=1; --i) x=pre[x][i],write(x),putchar(' ');
    	}
    	
    	#undef int
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    堆内存和栈内存
    链表
    爬虫---正则表达式
    剑指offer---二维数组中的查找
    基于C#开发的俄罗斯方块
    Java第十天
    软考错题合集之11-05-AM
    软考错题合集之11-11-AM
    软考错题合集之12-05-AM
    GOF之模板模式
  • 原文地址:https://www.cnblogs.com/ilverene/p/11360980.html
Copyright © 2011-2022 走看看