HDU 5715

看的别人的博客写的很好点击打开链接

代码如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;
typedef long long ll;
#define rep(i,n) for(int i = 0 ; i<(int)n;i++)
#define rep1(i,x,y) for(int i=(int)x;i<=(int)y;i++)
#define lowbit(x) (x&-x)

const int N =10010;

struct trie{
    int son[N*32][2], tim[N*32], tot;
    void init(){
        son[0][0] = son[0][1] = tot = 0;
        tim[0] = 1;
    }
    void insert(int val){
        int t = 0;
        for(int i = 30; i >= 0; --i){
            int c = (val >> i) & 1;
            if(son[t][c] == 0){
                son[t][c] = ++tot;
                son[tot][0] = son[tot][1] = tim[tot] = 0;
            }
            t = son[t][c];
            tim[t]++;
        }
    }
    void del(int val){
        int t = 0;
        for(int i = 30; i >= 0; --i){
            int c = (val >> i) & 1;
            int tt = t;
            t = son[t][c];
            tim[t]--;
            if(tim[t] == 0){
                son[tt][c] = 0;
                break;
            }
        }
    }
    int query(int val){
        int ret = 0, t = 0;
        for(int i = 30; i >= 0; --i){
            int c = (val >> i) & 1;
            if(son[t][c^1]){
                t = son[t][c^1];
                ret += (1 << i);
            }
            else {
                t = son[t][c];
            }
        }
        return ret;
    }
}tree[15];

int n,m,L;
bool d[N][11];
int a[N];
bool judge(int x){
    memset(d , 0 , sizeof(d));
    d[0][0] = 1;
    rep(i , m + 1) tree[i].init();
    tree[0].insert(0);

    for(int i = 1 ; i<=n ; i++){
         rep(j , m){
             if(i > L && d[i - L - 1][j])
                   tree[j].del(a[i - L - 1]);
         }
         for(int j = m ; j>=1 ; j--){
             if(tree[j - 1].query(a[i]) >= x){
                    d[i][j] = true;
                    tree[j].insert(a[i]);
             }
         }
    }
    return d[n][m];
}
int main()
{
    int T , kase = 1;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&n,&m,&L);
        rep1(i,1,n) scanf("%d",&a[i]) , a[i]^=a[i-1];
        int l = 0 , r = 1e9 + 100;
        while(l < r){
            //cout<<l <<" "<<r<<endl;
            int mid =(l + r)/2;
            if(judge(mid)) l = mid + 1;
            else r = mid;
        }
        printf("Case #%d:\n%d\n",kase++,l - 1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值