标签:
题意:
n个数分成m段,每段偶数个数,最小化和最大段的半个区间的数字和。
分析:
先想到了二分,dp求能分成的最小段数。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int dp[40010][2],sum[40010],n,m,d; int judge(int x){ dp[0][0]=0; dp[0][1]=INF; for(int i=2;i<=n;++i){ dp[i][0]=dp[i][1]=INF; for(int l=1;l<=d&&(i-2*l)>=0;++l){ if(sum[i]-sum[i-l]>x)break; if(sum[i-l]-sum[i-2*l]<=x){ dp[i][0]=min(dp[i][0],dp[i-2*l][1]+1); dp[i][1]=min(dp[i][1],dp[i-2*l][0]+1); } } } return dp[n][(m-1)%2]>m-1; } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&d); int a; sum[0]=0; for(int i=1;i<=n;++i) { scanf("%d",&a); sum[i]=sum[i-1]+a; } if(n%2||n<2*(m-1)||n>2*d*(m-1)) { printf("BAD\n");continue; } int l=1,r=sum[n]; while(l<=r){ int mid=(l+r)>>1; if(judge(mid))l=mid+1; else r=mid-1; } printf("%d\n",l); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zsf123/p/4909715.html