BZOJ 4069 [Apio2015]巴厘岛的雕塑 ——贪心

自己首先想了一种方法$f(i)$表示前$i$个最小值为多少。

然而发现位运算并不满足局部最优性。

然后我们可以从高到低贪心的判断,使得每一组的和在一个特定的范围之内。

还要特判最后一个Subtask,

想了想不用特判的办法,觉得bitset压不过去,就没写。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define llinf 10000000000000000LL
#define mp make_pair
 
int n,a,b;
ll y[2005],ans=llinf,upper,lower=0;
bool f[2][2005];
int g[2005];
 
bool test()
{
    int now=0,pre=1; memset(f[now],false,sizeof f[now]); f[0][0]=true;
    F(j,0,b-1)
    {
        now^=1; pre^=1; memset(f[now],false,sizeof f[now]);
        F(i,0,n-1) if (f[pre][i]) F(k,i+1,n)
        if ((y[k]-y[i]|lower)<=upper)
        {
            f[now][k]=true;
            if (k==n&&j+1>=a) return true;
        }
    }
    return false;
}
 
bool test2()
{
    memset(g,0x3f,sizeof g);
    g[0]=0;F(i,1,n) F(j,0,i-1) if ((y[i]-y[j]|lower)<=upper) g[i]=min(g[j]+1,g[i]);
    return g[n]<=b;
}
 
int main()
{
    scanf("%d%d%d",&n,&a,&b);
    F(i,1,n) scanf("%lld",&y[i]);
    F(i,1,n) y[i]+=y[i-1];
    D(i,40,0)
    {
        memset(f,false,sizeof f);
        upper=((1LL<<i)-1);upper+=lower;
        if ((n<=500&&!test())||(n>500&&!test2())) lower+=1LL<<i;
    }
    printf("%lld\n",lower);
}

  

转载于:https://www.cnblogs.com/SfailSth/p/6776888.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值