zoukankan      html  css  js  c++  java
  • 题解「JOI 2014 Final 年轮蛋糕」

    二分套路题,想到可以二分最小块大小,但是 ( ext{check}) 函数是个问题。

    这里给出两种 ( ext{check}) 的实现,时间复杂度分别为 (O(nlog n))(O(n))

    (O(n log n)) 的暴力做法:枚举每个 (i)( ext{lower_bound}) 一个 (j),再根据 (j)( ext{lower_bound}) 一个 (k),满足 (sumlimits_{ileq xleq j} a_xgeq mid,sumlimits_{j< xleq k}a_xgeq mid)

    (O(n)) 的做法:枚举每个 (i),再用两个指针 (p,q) 维护满足 (sumlimits_{pleq xleq i} a_xgeq mid)(sumlimits_{i<xleq q}a_xgeq mid),其中 (p) 为满足条件的最大的下标,(q) 为满足条件的最小的下标,这两个量都有单调性,所以使用 ( ext{two-pointer}) 维护即可。

    那么就可以在 (O(nlog sum a_i))(O(n log^2 sum a_i)) 的时间复杂度内解决该问题。

    #include<cstdio>
    typedef long long ll;
    ll n,sum; int a[100005]; 
    inline int read() {
    	register int x=0,f=1;register char s=getchar();
    	while(s>'9'||s<'0') {if(s=='-') f=-1;s=getchar();}
    	while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
    	return x*f;
    }
    inline bool check(ll val) {
    	int p=0,q=0; ll sum1=0,sum2=0;
    	for(register int i=0;i<n;++i) {
    		sum1+=a[i];sum2-=a[i];
    		while(p<=i&&sum1-a[p]>=val) {sum1-=a[p];++p;}
    		while(q<=n-1&&sum2<val) {sum2+=a[q];++q;}
    		if(sum2<val) return 0;
    		if(sum1>=val&&sum-sum1-sum2>=val) return 1; 
    	}
    	return 0;
    }
    int main() {
    	n=read(); 
    	for(register int i=0;i<n;++i) sum+=(a[i]=read());
    	ll l=0,r=sum,res=0;
    	while(l<=r) {
    		ll mid=l+r>>1;
    		if(check(mid)) l=mid+1,res=mid;
    		else r=mid-1;
    	}
    	printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    【Day3】4.Xpath语法与案例
    【Day3】3.提取商城分类结构
    【Day3】2.re模块使用案例
    【Day3】1.正则表达式
    【Day2】4.第三方模块的安装与使用
    【Day2】3.面向对象编程
    【Day2】2.函数
    【Day2】1.循环结构
    命令行切换目录
    D
  • 原文地址:https://www.cnblogs.com/tommy0103/p/13816661.html
Copyright © 2011-2022 走看看