zoukankan      html  css  js  c++  java
  • loj 3301 「联合省选 2020 A」魔法商店

    题目传送门

      传送门

      整个联考的区分度主要在会不会保序回归,次要在常数,有毒。。。

      关于以下使用的定理和结论的证明以及定义,请自行翻 2018 集训队论文。因为我都不会证。

      显然问题是给定一个拟阵 $M$ 和两个基 $I_a$ 以及 $I_b$,定义 $w(I) = sum_{xin I} z_x$,要求寻找一组系数 $z_x$,满足 $w(I_a)$ 最小,$w(I_b)$ 最大,并且最小化回归代价 $sum (z_x - v_x)^2$。 

    定理1 如果 $I, J$ 都是 $M$ 的独立集,那么交换图 $D_M(I)$ 中存在关于 $Iackslash J$ 以及 $J ackslash I$ 的完美匹配

      使用强基交换定理归纳。具体过程见论文。

      考虑对于 $I_a -{x} + {y}$ 得到的新的基,要求满足 $z_x leqslant z_y$,如果所有都满足这个限制,根据定理1,显然任意一个基都满足 $w(I_a) leqslant w(I)$。

      然后直接贴保序回归的板子就完事了。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define ull unsigned ll
    
    const ll llf = (signed ll) (~0u >> 3);
    
    typedef class Edge {
      public:
        int ed, nx;
        ll r;
    
        Edge(int ed, int nx, ll r) : ed(ed), nx(nx), r(r) {  }
    } Edge;
    
    typedef class MapManager {
      public:
        vector<int> h;
        vector<Edge> E;
    
        MapManager(int n) {
          h.assign(n + 1, -1);
          E.clear();
        }
        ~MapManager() {
          h.clear();
          E.clear();
        }
        void add_edge(int u, int v, ll r) {
          E.emplace_back(v, h[u], r);
          h[u] = (signed) E.size() - 1;  
        }
        Edge& operator [] (int p) {
          assert(p < (signed) E.size());
          return E[p];
        }
    } MapManager;
    
    typedef class Network {
      public:
        int S, T;
        vector<int> cur, div;
        MapManager g;
    
        Network(int S, int T) : S(S), T(T), g(T) {
          div.resize(T + 1);
        }
    
        void add_edge(int u, int v, ll w) {
          g.add_edge(u, v, w);
          g.add_edge(v, u, 0);
        }
    
        bool bfs() {
          fill(div.begin(), div.end(), 0);
          queue<int> Q;
          Q.push(S);
          div[S] = 1;
          while (!Q.empty()) {
            int p = Q.front();
            Q.pop();
            for (int i = g.h[p]; ~i; i = g[i].nx) {
              int e = g[i].ed;
              if (g[i].r && !div[e]) {
                div[e] = div[p] + 1;
                Q.push(e);
              }
            }
          }
          return div[T];
        }
    
        ll dfs(int p, ll mf) {
          if (p == T || !mf) {
            return mf;
          }
          ll flow = 0, f;
          for (int& i = cur[p]; ~i; i = g[i].nx) {
            int e = g[i].ed;
            if (div[e] == div[p] + 1 && (f = dfs(e, min(mf, g[i].r))) > 0) {
              g[i].r -= f;
              g[i ^ 1].r += f;
              flow += f;
              if (!(mf -= f))
                break;
            }
          }
          return flow;
        }
    
        ll dinic() {
          ll ret = 0;
          while (bfs()) {
            cur = g.h;
            dfs(S, llf);
          }
          return ret;
        }
    
        vector<bool> get_S() {
          vector<bool> ret (T + 1, false);
          queue<int> Q;
          Q.push(S);
          ret[S] = true;
          while (!Q.empty()) {
            int p = Q.front();
            Q.pop();
            for (int i = g.h[p]; ~i; i = g[i].nx) {
              int e = g[i].ed;
              if (g[i].r && !ret[e]) {
                ret[e] = true;
                Q.push(e);
              } 
            }
          }
          return ret;
        }
    } Network;
    
    const int bzmax = 64;
    
    typedef class LinearBasis {
      public:
        ull a[bzmax];
    
        void clear() {
          memset(a, 0, sizeof(a));
        }
        bool insert(ull x, bool chk = false) {
          for (int i = bzmax; i-- && x; ){
            if ((x >> i) & 1)
              x ^= a[i];
            if ((x >> i) & 1) {
              !chk && (a[i] = x);
              return true;
            }
          }
          return false;
        }
    } LinearBasis;
    
    const int N = 1e3 + 3;
    
    int n, m;
    int z[N], v[N];
    ull a[N];
    vector<int> A, B;
    
    void dividing(int l, int r, vector<int> P, vector<pair<int, int>> E, vector<int> org) {
      if (l == r) {
        for (auto x : P) {
          z[org[x]] = l;
        }
        return;
      }
      if (P.empty()) {
        return;
      }
      auto _P = P;
      int n = P.size();
      vector<int> norg(n);
      sort(_P.begin(), _P.end());
    #define get(x) (lower_bound(_P.begin(), _P.end(), x) - _P.begin())
      for (auto& x : P) {
        int y = org[x];
        norg[x = get(x)] = y; 
      }
      int mid = (l + r) >> 1;
      Network network (n, n + 1);
      for (auto& e : E) {
        e.first = get(e.first);
        e.second = get(e.second);
        network.add_edge(e.first, e.second, llf);
      }
      for (int x = 0; x < n; x++) {
        int y = norg[x];
        ll dx = ((mid - v[y]) << 1) + 1;
        if (dx < 0) {
          network.add_edge(n, x, -dx);
        } else if (dx > 0) {
          network.add_edge(x, n + 1, dx);
        }
      }
      network.dinic();
      auto inS = network.get_S();
    //  for (int i = 0; i < n; i++) {
    //    cerr << "(" << norg[i] << ", " << inS[i] << ") "; 
    //  }
    //  cerr << '
    ';
      vector<int> pL, pR;
      vector<pair<int, int>> eL, eR;
      for (int i = 0; i < n; i++) {
        if (inS[i]) {
          pR.push_back(i);
        } else {
          pL.push_back(i);
        }
      }
      for (auto e : E) {
        int u = e.first, v = e.second;
        if (inS[u] && inS[v]) {
          eR.push_back(e);
        } else if (!inS[u] && !inS[v]) {
          eL.push_back(e);
        }
      }
    #undef get
      dividing(l, mid, pL, eL, norg);
      dividing(mid + 1, r, pR, eR, norg);
    }
    
    LinearBasis lb;
    int main() {
      scanf("%d%d", &n, &m);
      for (int i = 1; i <= n; i++) {
        scanf("%llu", a + i);
      }
      int mi = 1e9, mx = -1;
      for (int i = 1; i <= n; i++) {
        scanf("%d", v + i);
        mi = min(mi, v[i]);
        mx = max(mx, v[i]);
      }
      vector<int> p, org;
      vector<pair<int, int>> E0;
      for (int i = 1; i <= n; i++) {
        p.push_back(i);
      }
      org = p;
      org.insert(org.begin(), 0);
      A.resize(m);
      vector<bool> in (n + 1, false);
      for (auto& x : A) {
        scanf("%d", &x);
        in[x] = true;
      }
      for (int i = 0; i < m; i++) {
        lb.clear();
        for (int j = 0; j < m; j++) {
          if (i ^ j) {
            lb.insert(a[A[j]]);
          }
        }
        for (int p = 1; p <= n; p++) {
          if (!in[p] && lb.insert(a[p], true)) {
            E0.emplace_back(A[i], p);
    //        cerr << A[i] << " <= " << p << '
    ';
          }
        }
      }
      for (auto x : A) {
        in[x] = false;
      }
      B.resize(m);
      for (auto& x : B) {
        scanf("%d", &x);
        in[x] = true;
      }
      for (int i = 0; i < m; i++) {
        lb.clear();
        for (int j = 0; j < m; j++) {
          if (i ^ j) {
            lb.insert(a[B[j]]);
          }
        }
        for (int p = 1; p <= n; p++) {
          if (!in[p] && lb.insert(a[p], true)) {
            E0.emplace_back(p, B[i]);
    //        cerr << p << " <= " << B[i] << '
    ';
          }
        }
      }
      dividing(mi, mx, p, E0, org);
      ll ans = 0;
      for (int i = 1; i <= n; i++) {
        ans += 1ll * (z[i] - v[i]) * (z[i] - v[i]);
      }
      printf("%lld
    ", ans);
      return 0;
    }
  • 相关阅读:
    UML 基础知识
    制作嵌入式根文件系统
    oracle 学习之 PL/SQL
    Password for '(null)' GNOME keyring:
    oracle 学习笔记
    lua关于编译后无法使用
    android,wince,windows,ios mms 网络电台收音机,小巧,兼容性好,性能高
    lua批量编译目前支持5.2,5.1
    lua关于编译后无法使用
    dlna support windows
  • 原文地址:https://www.cnblogs.com/yyf0309/p/13186940.html
Copyright © 2011-2022 走看看