扫描线

又到了noip的时节,

我想起了扫描线。

以前也只做过一道题。

我试着裸打一个扫描线,pku 的 atlantis。

 

 

附上另一道我几乎是直接抄的程序,虽然没有交(只过了编译),但是实在抱歉。。

//复健用 仅为纪念 
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define M 2001
int read(){
    int x=0,fh=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*fh;
}
int N,A,B,g[M];
bool f[M][M];
ll s[M],ans=0;

bool check(ll sum,ll ans,int bit){
    return (sum>>(bit+1)|ans==ans)&&(((sum>>bit)&1)==0);
}

void work1(){
    for(int i=(int)log2(s[N]);i>=0;i--){
        memset(f,0,sizeof(f));
        f[0][0]=true;
        for(int j=1;j<=N;j++){
            for(int k=1;k<=min(j,B);k++){
                f[j][k]=false;
                for(int l=1;l<=j&&!f[j][k];l++)
                    f[j][k]|=(f[l-1][k-1])&&(check(s[j]-s[l-1],ans,i));
            }
        }
        bool b=false;
        for(int i=A;i<=B&&!b;i++){
            b|=f[N][i];
        }
        ans=ans<<1|!b;
    }
}

void work2(){
    for(int i=(int)log2(s[N]);i>=0;i--){
        g[0]=0;
        for(int j=1;j<=N;j++){
            g[j]=B+1;
            for(int k=1;k<=j;k++)
                if(g[k-1]+1<g[j]&&check(s[j]-s[k-1],ans,i))
                    g[j]=g[k-1]+1;
        }
        ans=(ans<<1)|(g[N]>B);
    }
}

int main()
{
    freopen("inp.in","r",stdin);
    N=read();A=read();B=read();s[0]=0;
    for(int i=1;i<=N;i++){
        int x=read();
        s[i]=s[i-1]+(ll)x;
    }
    if(A>1)work1();
    else work2();
    printf("%I64d",ans);
}

 

posted on 2016-09-09 21:38  Crisscross  阅读(184)  评论(0编辑  收藏  举报