1044: [HAOI2008]木棍分割

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1393  Solved: 497
[Submit][Status]

Description

有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007。。。

Input

输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍的长度.

Output

输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.

Sample Input

3 2
1
1
10

Sample Output

10 2

两种砍的方法: (1)(1)(10)和(1 1)(10)
数据范围
n<=50000, 0<=m<=min(n-1,1000).
1<=Li<=1000.

前半部分为极水的二分,后半部分的DP优化很经典.用f[i][j]表示砍了i此到第j个末的方法种数,直接用一般的DP暴空间+时间,改为滚动数组后还是TLE。可以发现DP中后一层完全有前一层的一个连续区间决定的,且这些区间起点终点都是递增的。便可借此优化。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 50010
#define MAXM 1010
#define VAL1 10007
#define VAL2 1100
int le[MAXN];
int n,m;
int f[][MAXN];
int ps[MAXN]; bool ok(int x)
{
int nowl=,tt=m;
int i;
for (i=;i<=n;i++)
{
if (le[i]>x)return false;
nowl+=le[i];
if (nowl>x)
{
nowl=le[i];
tt--;
if (tt==-)return false;
}
}
if (tt<=-)return false;
return true;
}
void deal(int &x,int y)
{
x+=y;x%=VAL1;
}
int q[MAXN*];
int main()
{
freopen("input.txt","r",stdin);
int i,j;
scanf("%d%d",&n,&m);
int sum=;
for (i=;i<=n;i++)scanf("%d",le+i),sum+=le[i];
for (i=;i<=n;i++)ps[i]=ps[i-]+le[i];
ps[]=le[];
int ans1,ans2=;
int l=,r=sum,mid;
while (l+<r)
{
mid=(l+r)>>;;
if (ok(mid))
{
r=mid;
}else
{
l=mid;
}
}
ans1=r;
int * a,*b;
int ope,clo,res;
f[][]=;
a=f[];b=f[];
for (i=;i<m;i++)
{
res=a[];
ope=,clo=;
q[]=;
for (j=;j<=n;j++)
{
while (ope<=clo&&ps[j]-ps[q[ope]]>ans1)
{
res-=a[ope++];
if(res<)res+=VAL1;
}
b[j]=res;
res+=a[++clo];
q[clo]=j;
res%=VAL1;
}
for (j=n-;j>=;j--)//这里不是n,Wa了好久
{
if (ps[n]-ps[j]>ans1)break;
ans2+=b[j];
ans2%=VAL1;
}
memset(a,,sizeof(int)*MAXN);
swap(a,b);
} /*
f[0][0]=1;
for (i=1;i<=n;i++)
{
for (j=i;j>0;j--)
{
if (ps[i]-ps[j-1]>ans1)break;
for (k=0;k<m;k++)
{
deal(f[i%VAL2][k+1],f[(j-1)%VAL2][k]);
}
}
}
for (i=n;i>=1;i--)
{
if (ps[n]-ps[i]>ans1)break;
ans2=(ans2+f[i%VAL2][m])%VAL1;
}*/
printf("%d %d\n",ans1,ans2); }

最新文章

  1. 知方可补不足~sqlserver中使用ROW_NUMBER进行的快速分页
  2. Ubuntu Gnome 14.04.2 lts 折腾笔记
  3. 使用https协议解决掉顽固不化的已解密的登录请求
  4. Java编程语言中sleep()和yield()的区别
  5. r.js 前端项目打包
  6. 学习Linux第六天
  7. 会话—cookie
  8. SIFT算法:KeyPoint找寻、定位与优化
  9. [Swust OJ 772]--Friend(并查集+map的运用)
  10. Modelbuilder进阶教程
  11. 《基于Node.js实现简易聊天室系列之详细设计》
  12. 案例:数据库open时报错ORA-1172,ORA-1151 处理
  13. [Go] golang的select多路选择功能
  14. oracle中的trim()函数详解
  15. C++与C#互调dll的实现步骤
  16. C#如何通过反射调用带有ref或者out的参数的方法
  17. Locust性能测试1-环境准备与基本使用
  18. Django实战(7):改造ProductList界面
  19. 转 web前端性能分析--原理篇
  20. Linux和Docker常用命令

热门文章

  1. 详解ExplosionField的使用,实现View的粉碎效果
  2. Debian 6解决中文乱码
  3. Hashtable和HashMap类
  4. 学习笔记_过滤器应用_1(分ip统计网站的访问次数)
  5. 记录关于使用ADO.NET 连接池连接Oracle时Session信息不更新的坑
  6. linux命令行执行db2存储过程
  7. libCURL动态分配buffer——节约内存
  8. JDBC实现往MySQL插入百万级数据
  9. 用crontab、crond在嵌入式系统中添加定时任务
  10. 某Python群的入群题目