zoukankan      html  css  js  c++  java
  • 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
    ",lower);
    }
    

      

  • 相关阅读:
    Java验证码
    Java内存泄漏问题
    Java常见异常总结
    Java编码与乱码问题
    Spring:源码解读Spring IOC原理
    Quartz 定时邮件发送多个备份文件
    spring-boot 多线程
    java并发基础
    Java多线程中wait语句的具体使用技巧
    多线程的死锁
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6776888.html
Copyright © 2011-2022 走看看