zoukankan      html  css  js  c++  java
  • Avito Code Challenge 2018

    D. Bookshelves

    注意:sum[ ii ]表示第 ii 块的所有数字和,因为有序,实际上就是一个区间和。

    题解:二进制枚举答案ans,怎么枚举呢?从高位到低位放1,如果这个序列划分成m块后,能够sum[1] & sum[2] & ···· & sum[m] = ans,那么这位能够放1。dp[ i ][ j ] 表示 1 ~ i 这i个数能否划成 j 个块,使得 sum[1] & sum[2] & ·····  & sum[j] = ans。dp[ i ][ j ] = 1 only if some p ( j - 1 <= p < i ), dp[ p ][ j - 1 ] = 1 and ( a[ i ] - a[ p ] )&x == x。意思是当存在 1 ~ p 这 p 个数能划分成 j - 1 块,所以当第 j 块的区间和与上 x 等于 x 的时候,这 i  个数能划分成 j 块。怎么判断这些块的与等于ans?显然不能求出所有的区间和然后再进行与操作,转化一下,如果 a & x = x, b & x = x, c & x = x,则 a & b & c = x。正确性我没考证!!!所以这需要单独的判断每个区间就行了。

    感受:连着两场的dp都没写出来,dp非常有意思就是有点难理解。

    #pragma warning(disable:4996)
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define mem(arr, in) memset(arr, in, sizeof(arr))
    using namespace std;
    
    const int maxn = 100;
    
    bool dp[maxn][maxn];
    ll n, m, ans, a[maxn];
    
    bool check(ll x) {
        mem(dp, 0);
        dp[0][0]=1;
        for (int i = 1; i <= n; i++) {    // 枚举 i 个数
            for (int j = 1; j <= i; j++) {   // 枚举块,所以写成 j <= min( m, i ) 也行
                for (int k = j - 1; k < i; k++) if (dp[k][j - 1] && ((a[i] - a[k]) & x) == x) dp[i][j] = 1;   // 一定要从 j - 1 开始
            }
        }
        return dp[n][m];
    }
    
    int main()
    {
        while (cin >> n >> m) {
            for (int i = 1; i <= n; i++) cin >> a[i], a[i] += a[i - 1];
            ans = 0;
            for (int i = 60; i >= 0; i--) if (check(ans | 1LL << i)) ans |= 1LL << i;
            cout << ans << endl;
        }
        return 0;
    }

     E. Addition on Segments

    题解:考虑每个点,包含这个点的区间能够产生不同的数,实际上就是考虑这些区间的子集(2^n-1),先用线段树标记一下,用bitset暴力枚举。

    感受:这道题我也没完全搞明白,题解只是一个笑话。重点依然是bitset这个数据结构!!!!其实不是状态转移了,就是bitset优化的暴力而已。对于一个集合,bitset可以枚举出这个集合的任意一个子集的和。注意bitset的每一位代表着什么,然后手动模拟一些数据,体验一下移位和或这两个操作的意思。一定要明白bitset里面的每一位表示什么

    #pragma warning(disable:4996)
    #include<bitset>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    
    #define lson root<<1
    #define rson root<<1|1
    
    #define mem(arr, in) memset(arr, in, sizeof(arr))
    using namespace std;
    
    const int maxn = 10004;
    
    using bs = bitset<maxn>;
    
    int n, q;
    vector<int> v[4 * maxn];
    
    void Update(int l, int r, int root, int L, int R, int x) {
        if (l > R || r < L) return;
        if (L <= l && r <= R) {
            v[root].push_back(x);
            return;
        }
        int mid = (l + r) >> 1;
        Update(l, mid, lson, L, R, x);
        Update(mid + 1, r, rson, L, R, x);
    }
    
    bs ans;
    
    void DFS(int l, int r, int root, bs dp) {
        bs go = dp;
        for (auto op : v[root]) go |= go << op;
        if (l == r) {
            ans |= go;
            return;
        }
        int mid = (l + r) >> 1;
        DFS(l, mid, lson, go);
        DFS(mid + 1, r, rson, go);
    }
    
    int main()
    {
        while (scanf("%d %d", &n, &q) != EOF) {
            for (int i = 1; i <= q; i++) {
                int l, r, x;
                scanf("%d %d %d", &l, &r, &x);
                Update(1, n, 1, l, r, x);
            }
            
            bs dp;
            dp[0] = 1;
            DFS(1, n, 1, dp);
    
            int cnt = 0;
            for (int i = 1; i <= n; i++) if (ans[i]) cnt++;
    
            printf("%d
    ", cnt);
            for (int i = 1; i <= n; i++) if (ans[i]) {
                printf("%d ", i);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    redis
    基础加强(@注解)
    过滤器Filter
    监听器
    ajax
    Java 常用类Math、System、时间相关Calender和Date
    Java Object、Scanner、String 、生成jar包
    Java 内部类、eclipse、包
    Java 面向对象之抽象
    Java 面向对象三大特征之多态
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9112063.html
Copyright © 2011-2022 走看看