[APIO2015]Bali Sculptures

来源:互联网 发布:淘宝adidas女款夏季 编辑:程序博客网 时间:2024/05/20 08:26

看到这种求位运算的问题一定要想直接对答案贪心啊,从高位枚举到低位,设当前的位为pos,pos之前贪心得到的答案为ans。
现在的问题就是能否找到一种方案,使得pos这一位为0,而且满足这种方案算出来的答案的前若干位与ans相同。
考虑设f[i][j]表示前i个数,分j份能否满足条件,0为满足,若存在一个k使得f[k][j1]==0,(s[i]s[k])and(1<<pos)==0,(((ans|((s[i]s[j])))>>pos))==(ans>>pos)
则f[i][j]=0.这样做是n3log的。
对于最后一个子任务,考虑到a=1,还是按位贪心,设g[i]表示前i个数至少分多少块满足条件,g[n]与b比较即可。

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#include<map>#include<climits>#include<cmath>#define DB double#define X first#define Y second#define MP make_pair#define INF 0x3f3f3f3f#define LL long long#define pii pair<int,int>#define pll pair<LL,LL>#define int LL#define DEBUG(...) fprintf(stderr,__VA_ARGS__)using namespace std;template<typename T>void Read(T& x){    x=0;char c;int flag=0,sgn=1;    while(c=getchar())    {        if(c=='-')sgn=-1;        else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;        else if(flag)break;    }    x*=sgn;}const int MAXN=2001;LL f[MAXN][MAXN],n,a,b,g[MAXN],ans=0,num[MAXN],s[MAXN];void fucker(){    f[0][0]=0;    for(int i=1;i<MAXN;i++)f[0][i]=1;    for(int pos=59;pos>=0;pos--)    {        if(pos==1)            pos=1;        int flag=1LL;        for(int k=1;k<=b;k++)            for(int i=k;i<=n;i++)            {                f[k][i]=1LL;                for(int j=k-1;j<i;j++)                {                    bool a=(((s[i]-s[j])&(1LL<<(pos))))==0,b=((((ans|((s[i]-s[j])))>>pos))==(ans>>pos));                    f[k][i]=min(f[k][i],f[k-1][j]==0&&a&&b?0LL:1LL);                }            }        for(int k=a;k<=b;k++)            if(f[k][n]==0)flag=0;        ans|=(flag<<pos);    }    cout<<ans<<endl;}void lover(){    for(int pos=60;pos>=0;pos--)    {        for(int i=1;i<=n;i++)        {            g[i]=(LL)INF;            for(int j=0;j<i;j++)            {                   int tmp=0;                bool a=((((s[i]-s[j])&(1LL<<pos)))==0),b=((((ans|((s[i]-s[j])))>>pos))==(ans>>pos));                if(a&&b)                    tmp=g[j]+1;                else                    tmp=3000;                //DEBUG("%lld %lld\n",g[i],tmp);                g[i]=min(g[i],tmp);            }        }        if(g[n]>b)ans|=(1LL<<pos);//printf("%lld\n",pos);    }    cout<<ans<<endl;}main(){    freopen("bali.in","r",stdin);    freopen("bali.out","w",stdout);    Read(n),Read(a),Read(b);    for(int i=1;i<=n;i++)        Read(num[i]),s[i]=num[i]+s[i-1];    if(a==1)lover();    else fucker();}
0 0
原创粉丝点击