zoukankan      html  css  js  c++  java
  • [Usaco2014 Open]Gold Fair Photography(hash)

    最近做了usaco2014 open的金组,果然美帝的题还是没有太简单啊QAQ,被每年的月赛骗了QAQ

    不过话说官方题解真心棒(虽然英文的啃得好艰难,我英语渣你们别鄙视我= =),标程超级优美QAQ

    按照标程打,学到了好多STL的用法= =(没办法,我c++底子弱)

    这道题嘛,可以发现对于每个区间,只要左边界确定,可能的集合就一共只有8种了

    考虑前缀和,发现若L~R为可行解,则对于所有种类的牛,有S[R]-S[L]=K或0

    如何防止枚举K,可以发现在该集合中B的s[L][bi]减去s[L][b0]就行了

    那么就hash,枚举集合B,求出hash值,直接做就行了

    CODE:(直接贴标程了,Map真的用的是神出鬼没啊QAQ)

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cassert>
    #include <map>
    
    using namespace std;
    
    #define MAXN 100010
    #define GROUPS 8
    
    int MB[MAXN][GROUPS];
    int MF[MAXN][GROUPS];
    int PS[MAXN][GROUPS];
    
    int main() {
      freopen("fairphoto.in", "r", stdin);
      freopen("fairphoto.out", "w", stdout);
    
      int N, K; cin >> N >> K;
      vector<pair<int, int> > A(N);
      for(int i = 0; i < N; i++) {
        cin >> A[i].first >> A[i].second;
        A[i].second--;
      }
      sort(A.begin(), A.end());
    
      /* Construct backstep masks */
      for(int i = 0; i < GROUPS; i++) {
        MB[0][i] = 1 << A[0].second;
      }
      for(int i = 1; i < N; i++) {
        int bt = 1 << A[i].second;
    
        MB[i][0] = bt;
        for(int j = 1; j < GROUPS; j++) {
          if(MB[i - 1][j] & bt) {
            MB[i][j] = MB[i - 1][j];
          } else {
            MB[i][j] = bt | MB[i - 1][j - 1];
          }
        }
      }
    
      /* Construct forward step masks */
      for(int i = 0; i < GROUPS; i++) {
        MF[N - 1][i] = 1 << A[N - 1].second;
      }
      for(int i = N - 2; i >= 0; i--) {
        int bt = 1 << A[i].second;
    
        MF[i][0] = bt;
        for(int j = 1; j < GROUPS; j++) {
          if(MF[i + 1][j] & bt) {
            MF[i][j] = MF[i + 1][j];
          } else {
            MF[i][j] = bt | MF[i + 1][j - 1];
          }
        }
      }
    
      /* Construct partial sums */
      for(int i = 0; i < N; i++) {
        memcpy(PS[i + 1], PS[i], sizeof(PS[i]));
        ++PS[i + 1][A[i].second];
      }
    
      int result = -1;
      for(int j = K - 1; j < GROUPS; j++) {
        vector<int> V(1 + GROUPS);
        map<vector<int>, int> cost_map;
    
        /* Compute the earliest starts for given masks
         * and normalized partial sums. */
        for(int i = N - 1; i >= 0; i--) {
          int base = -1;
          int m = V[GROUPS] = MF[i][j];
          if(__builtin_popcount(m) <= j) continue;
          for(int k = 0; k < GROUPS; k++) {
            if(m & 1 << k) {
              if(base == -1) {
                base = PS[i][k];
              }
              V[k] = PS[i][k] - base;
            } else {
              V[k] = PS[i][k];
            }
          }
          cost_map[V] = A[i].first;
        }
    
        /* Find best start points for each ending position. */
        for(int i = 0; i < N; i++) {
          int base = -1;
          int m = V[GROUPS] = MB[i][j];
          if(__builtin_popcount(m) <= j) continue;
          for(int k = 0; k < GROUPS; k++) {
            if(m & 1 << k) {
              if(base == -1) {
                base = PS[i + 1][k];
              }
              V[k] = PS[i + 1][k] - base;
            } else {
              V[k] = PS[i + 1][k];
            }
          }
    
          map<vector<int>, int>::iterator it = cost_map.find(V);
          if(it != cost_map.end() && it->second < A[i].first) {
            result = max(result, A[i].first - it->second);
          }
        }
      }
    
      cout << result << endl;
      return 0;
    }


  • 相关阅读:
    hdu1238 Substrings
    CCF试题:高速公路(Targin)
    hdu 1269 迷宫城堡(Targin算法)
    hdu 1253 胜利大逃亡
    NYOJ 55 懒省事的小明
    HDU 1024 Max Sum Plus Plus
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1257 最少拦截系统
    HDU 1069 Monkey and Banana
    HDU 1104 Remainder
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4348900.html
Copyright © 2011-2022 走看看