zoukankan      html  css  js  c++  java
  • 百度之星复赛 1004 / hdu5715 二分dp+trie

    XOR 游戏

    Problem Description
     
    众所周知,度度熊喜欢XOR运算[(XOR百科)](http://baike.baidu.com/view/674171.htm)。

    今天,它发明了一种XOR新游戏,最开始,它有一个长度为N的数组,度度熊可以任意添加分割线,将数组划分为M段,且每段长度小于等于L

    当然这是个和XOR有关的游戏,度度熊希望所有分组内异或和的最小值最大。

    比如,长度为4的数组{1,2,3,4}L3,可以划分为{1|2,3,4} 或 {1,2|3,4} 或 {1,2,3|4},最小的异或值分别为1,3,0,所以选第二种分割方法。
     
    Input
     
    第一行为T,表示输入数据组数。

    对于每组数据,第一行包含三个整数N,M,L,第二行包含N个数,表示数组。

    1T300

    1N10000,1M10,1LN

    1Ai109
     
    Output
     
    对第i组数据,输出

    Case #i:

    然后输出一行,仅包含一个整数,表示满足条件分组方法的最小异或值。
     
    Sample Input
     
    2 4 2 3 1 2 3 4 4 3 2 5 4 3 2
     
    Sample Output
     
    Case #1: 3 Case #2: 2
     

    题解:

      二分答案check mid

      就是在划分m次的情况下 使得当前f[x][i] 表示前i个位置数划分成x快能否使得最小值得最大值大于mid

      维护长度L+1,将这些数的前缀放入trie中,尽量跑出当前能得到的最大值是否大于mid

      代码来自jiry

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    const int N = 1e4+20, M = 1e6+10, mod = 1e9+7, inf = 1e9+1000;
    typedef long long ll;
    
    int cas = 1,n,m,L,ans,tot,a[N];
    int f[11][N];
    struct ss{
        int ls,rs,sz;
    }tr[N*64];
    void ins(int x,int key,int v) {
        tr[x].sz += v;
        for(int i=30;~i;i--) {
            if(key&(1<<i)) {
                if(!tr[x].rs) {
                    tr[++tot]  = (ss) {0,0,0};
                    tr[x].rs = tot;
                }
                x = tr[x].rs;
            }
            else {
                if(!tr[x].ls) {
                    tr[++tot] = (ss) {0,0,0};
                    tr[x].ls = tot;
                }
                x = tr[x].ls;
            }
            tr[x].sz += v;
        }
    }
    int ask(int x,int key) {
        int ret = 0;
        for(int i=30;~i;i--) {
            if(key&(1<<i)) {
                if(tr[tr[x].ls].sz)ret += (1<<i),x = tr[x].ls;else x = tr[x].rs;
            }
            else {
                if(tr[tr[x].rs].sz) ret += (1<<i),x = tr[x].rs;else x = tr[x].ls;
            }
        }
        return ret;
    }
    int check(int x) {
        memset(f,0,sizeof(f));
        f[0][0] = 1;
        for(int j=1;j<=m;j++) {
            tr[tot = 1] = (ss) {0,0,0};
            for(int i=1;i<=n;i++) {
                if(f[j-1][i-1]) ins(1,a[i-1],1);
                if(i>L&&f[j-1][i-L-1]) ins(1,a[i-L-1],-1);
                f[j][i] = (ask(1,a[i])>=x);
            }
        }
        return f[m][n];
    }
    void solve() {
        scanf("%d%d%d",&n,&m,&L);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]), a[i] ^= a[i-1];
        int l = 0, r = 2e9+10;
        while(l<=r) {
            int mid = (l+r)>>1;
            if(check(mid)) l = mid + 1, ans = mid;
            else r = mid - 1;
        }
        printf("Case #%d:
    %d
    ",cas++,ans);
    }
    int main() {
        int T;
        scanf("%d",&T);
        while(T--) {
            solve();
        }
        return 0;
    }
  • 相关阅读:
    java 堆、栈、方法区/ 类变量、成员变量、局部变量
    native的详细用法
    《Java项目中classpath路径详解》
    事务四大特征:原子性,一致性,隔离性和持久性(ACID)
    Tomcat 配置文件server.xml详解
    linux下vim常用命令 (更新中...)
    #1572 小Hi与花盆
    leetcode 120. Triangle
    leetcode 174. Dungeon Game
    leetcode 368. Largest Divisible Subset
  • 原文地址:https://www.cnblogs.com/zxhl/p/5543470.html
Copyright © 2011-2022 走看看