zoukankan      html  css  js  c++  java
  • 【[HAOI2008]木棍分割】

    没写过几道的前缀和优化(dp)

    第一问是小学生难度的二分

    第二问就直接(dp)

    (dp[i][j])表示当前分割点在(i)之后,前面一共分割了(j)段的方案数

    利用前缀和单调性,通过二分预处理出每一个点往前能扩展到的最大位置,之后前缀和优化就可以啦

    但是发现这个样子空间会炸,而这个样子还没有办法滚动起来

    那好办交换一下状态的顺序就可以啦,就可以前缀和/滚动数组优化了

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 50005
    #define max(a,b) ((a)>(b)?(a):(b))
    const int mod=10007;
    int a[maxn],n,m;
    int dp[2][maxn],pre[2][maxn];
    int p[maxn],to[maxn];
    int ans;
    inline int read()
    {
    	char c=getchar();
    	int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    		x=(x<<3)+(x<<1)+c-48,c=getchar();
    	return x;
    }
    inline int check(int x)
    {
    	int now=0,tot=0;
    	for(re int i=1;i<=n;i++)
    	{
    		if(now+a[i]>x) now=a[i],tot++;
    		else now+=a[i];
    		if(tot>m) return 0;
    	}
    	return tot<=m; 
    }
    inline int find(int l,int r,int now)
    {
    	int t;
    	while(l<=r)
    	{
    		int mid=l+r>>1;
    		if(p[now]-p[mid]>ans) l=mid+1;
    			else r=mid-1,t=mid;
    	}
    	return t;
    }
    int l,r;
    int main()
    {
    	n=read(),m=read();
    	for(re int i=1;i<=n;i++) a[i]=read(),r+=a[i],l=max(l,a[i]);
    	for(re int i=1;i<=n;i++) p[i]=p[i-1]+a[i];
    	while(l<=r)
    	{
    		int mid=l+r>>1;
    		if(check(mid)) ans=mid,r=mid-1;
    			else l=mid+1;
    	}
    	printf("%d ",ans);
    	for(re int i=1;i<=n;i++)
    		to[i]=find(0,i-1,i)+1;
    	for(re int i=1;i<=n;i++) if(p[i]<=ans) dp[0][i]=1;
    	for(re int i=1;i<=n;i++) pre[0][i]=pre[0][i-1]+dp[0][i];
    	int o=0,cnt=0;
    	cnt=(cnt+dp[0][n])%mod;
    	for(re int i=2;i<=m+1;i++,o^=1)
    	{
    		memset(dp[o^1],0,sizeof(dp[o^1]));
    		for(re int j=1;j<=n;j++)
    			dp[o^1][j]=(dp[o^1][j]+pre[o][j-1]-(j-2<0?0:pre[o][to[j]-2])+mod)%mod;
    		pre[o^1][0]=0;
    		for(re int j=1;j<=n;j++)
    			pre[o^1][j]=(pre[o^1][j-1]+dp[o^1][j])%mod;
    		cnt=(cnt+dp[o^1][n])%mod;
    	}
    	printf("%d
    ",cnt);
    	return 0;
    }
    
  • 相关阅读:
    SCRIPT7002: XMLHttpRequest: 网络错误 0x2efe, 由于出现错误 00002efe 而导致此项操作无法完成
    经纬转换成point的sql
    build.xml
    ubuntu下安装vsftpd及vsftpd配置文件不见的解决办法
    500 OOPS: could not read chroot() list file:/etc/vsftpd.chroot_list
    【linux】su、sudo、sudo su、sudo -i的用法和区别
    Js获取上一月份
    BigDecimal工具类
    查询重复的记录
    Excel 合并单元格
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207887.html
Copyright © 2011-2022 走看看