zoukankan      html  css  js  c++  java
  • BZOJ 1044 [HAOI2008]木棍分割

    题解:

    第一问二分答案

    第二问用f[i][j]表示前i块分成j段的方案数

    但是MLE

    于是改变枚举顺序

    先枚举j,然后i这一层用滚动数组优化

    f[i][j]=sigma f[k][j-1](sum[i]-sum[k]<=ans)

    决策是一段区间,而且左端点单调,搞个指针维护最左的决策点

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=100009;
    const int mm=10007;
    
    int n,m;
    int s[maxn]={0};
    
    int tot=0;
    int l=0,r=0,mid=0,ans=0;
    
    int f[maxn]={0};
    int g[maxn]={0};
    
    int Isok(){
    	int last=0,cnt=0;
    	for(int i=1;i<=n;++i){
    		if(s[i]-s[last]>mid){
    			++cnt;last=i-1;
    		}
    	}
    	++cnt;
    	if(cnt>m)return 0;
    	else return 1;
    }
    
    int main(){
    	scanf("%d%d",&n,&m);++m;
    	for(int i=1;i<=n;++i){
    		scanf("%d",&s[i]);
    		l=max(l,s[i]);
    		s[i]+=s[i-1];
    	}
    	
    	r=1000000000;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(Isok()){
    			ans=mid;
    			r=mid-1;
    		}else{
    			l=mid+1;
    		}
    	}
    	printf("%d ",ans);
    	
    	for(int i=1;i<=n;++i){
    		if(s[i]<=ans)g[i]=1;
    		else g[i]=0;
    	}
    	for(int j=2;j<=m;++j){
    		for(int i=1;i<=j-1;++i)f[j]=0;
    		int tm=g[j-1],last=j-1;
    		for(int i=j;i<=n;++i){
    			while((s[i]-s[last]>ans)){
    				tm=(tm-g[last]+mm)%mm;++last;
    			}
    			f[i]=tm;
    			tm=(tm+g[i])%mm;
    		}
    		tot=(tot+f[n])%mm;
    //		for(int i=1;i<=n;++i)cout<<f[i]<<' ';
    //		cout<<endl;
    		for(int i=1;i<=n;++i)g[i]=f[i];
    	}
    	
    	printf("%d
    ",tot);
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    使用nginx搭建https服务器
    CentOS6.*安装gitolite
    Nginx 下配置SSL证书的方法
    Nginx Location配置总结
    最优二叉树(哈夫曼树)知识点
    utf8字节
    utf8字节
    nginx 配置日志
    nginx 配置日志
    elk 索引
  • 原文地址:https://www.cnblogs.com/zzyer/p/8503754.html
Copyright © 2011-2022 走看看