QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#349494#8315. Candy Adshos_lyricWA 0ms3940kbC++146.9kb2024-03-10 02:26:552024-03-10 02:26:56

Judging History

你现在查看的是最新测评结果

  • [2024-03-10 02:26:56]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3940kb
  • [2024-03-10 02:26:55]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")


// get0(u): should return a neighbor of u and remove it (or -1).
// get1(u): the same for reversed edge
template <class Get0, class Get1> struct SccDyn {
  int n;
  const Get0 get0;
  const Get1 get1;

  int l;
  vector<int> ids;
  int operator[](int u) const { return ids[u]; }

  SccDyn(int n_, Get0 get0_, Get1 get1_) : n(n_), get0(get0_), get1(get1_) {
    ids.assign(n, 0);
    us.clear();
    for (int u = 0; u < n; ++u) dfs0(u);
    l = 0;
    for (int j = n; --j >= 0; ) if (!~ids[us[j]]) { dfs1(us[j]); ++l; }
  }

  vector<int> us;
  void dfs0(int u) {
    if (!ids[u]) {
      ids[u] = -1;
      for (; ; ) {
        const int v = get0(u);
        if (!~v) break;
        dfs0(v);
      }
      us.push_back(u);
    }
  }
  void dfs1(int u) {
    if (!~ids[u]) {
      ids[u] = l;
      for (; ; ) {
        const int v = get1(u);
        if (!~v) break;
        dfs1(v);
      }
    }
  }

  vector<vector<int>> group() const {
    assert(~l);
    vector<vector<int>> uss(l);
    for (int u = 0; u < n; ++u) uss[ids[u]].push_back(u);
    return uss;
  }
};  // SccDyn
template <class Get0, class Get1>
SccDyn<Get0, Get1> sccDyn(int n, Get0 get0, Get1 get1) {
  return SccDyn<Get0, Get1>(n, get0, get1);
}
template <class Get> auto sccDyn(int n, Get get) {
  return sccDyn(
    n,
    [&](int u) -> int { return get(0, u); },
    [&](int u) -> int { return get(1, u); }
  );
}

////////////////////////////////////////////////////////////////////////////////


int N, W, H;
int P[50010][4];
int M;
vector<int> A, B;

struct Kdt {
  int nn;
  vector<int> us, os;
  struct Node {
    int t;
    int l, r;
    int mn[4], mx[4];
  };
  vector<Node> nodes;
  void build() {
    us.resize(N);
    for (int u = 0; u < N; ++u) us[u] = u;
    nn = 0;
    nodes.resize(2 * N - 1);
    os.assign(N, -1);
    buildRec(0, N, 0);
  }
  int buildRec(int jL, int jR, int dir) {
    const int o = nn++;
    Node &node = nodes[o];
    for (int d = 0; d < 4; ++d) node.mn[d] = node.mx[d] = P[us[jL]][d];
    if (jL + 1 == jR) {
      os[us[jL]] = o;
      node.t = us[jL];
      node.l = node.r = -1;
    } else {
      for (int j = jL + 1; j < jR; ++j) {
        for (int d = 0; d < 4; ++d) {
          chmin(node.mn[d], P[us[j]][d]);
          chmax(node.mx[d], P[us[j]][d]);
        }
      }
      const int jMid = jL + (jR - jL) / 2;
      std::nth_element(us.begin() + jL, us.begin() + jMid, us.begin() + jR,
                       [&](int u0, int u1) -> bool {
                         return (P[u0][dir] < P[u1][dir]); 
                       });
      node.l = buildRec(jL, jMid, (dir + 1) & 3);
      node.r = buildRec(jMid, jR, (dir + 1) & 3);
      node.t = max(nodes[node.l].t, nodes[node.r].t);
    }
    return o;
  }
  /*
         p[0] <= r
    l <= p[1]     
    a <= p[2] <= b
    c <= p[3] <= d
  */
  int take(int r, int l, int a, int b, int c, int d) {
    return takeRec(0, r, l, a, b, c, d);
  }
  int takeRec(int o, int r, int l, int a, int b, int c, int d) {
    Node &node = nodes[o];
    if (!~node.t) {
      return -1;
    }
    if (!(                      node.mn[0] <= r
          && l <= node.mx[1]
          && a <= node.mx[2] && node.mn[2] <= b
          && c <= node.mx[3] && node.mn[3] <= d)) {
      return -1;
    }
    if (!~node.l) {
      const int u = node.t;
      node.t = -1;
      return u;
    }
    int u = takeRec(node.l, r, l, a, b, c, d);
    if (!~u) {
      u = takeRec(node.r, r, l, a, b, c, d);
    }
    node.t = max(nodes[node.l].t, nodes[node.r].t);
    return u;
  }
  void restore(int u) {
    restoreRec(0, u);
  }
  void restoreRec(int o, int u) {
    Node &node = nodes[o];
    if (!~node.l) {
      node.t = u;
      return;
    }
    restoreRec((os[u] < node.r) ? node.l : node.r, u);
    node.t = max(nodes[node.l].t, nodes[node.r].t);
  }
};

int main() {
  for (; ~scanf("%d%d%d", &N, &W, &H); ) {
    for (int u = 0; u < N; ++u) for (int d = 0; d < 4; ++d) {
      scanf("%d", &P[u][d]);
    }
    scanf("%d", &M);
    A.resize(M);
    B.resize(M);
    for (int i = 0; i < M; ++i) {
      scanf("%d%d", &A[i], &B[i]);
      --A[i];
      --B[i];
    }
    
    Kdt kdt[2];
    vector<vector<int>> graph[2];
    for (int s = 0; s < 2; ++s) {
      kdt[s].build();
      graph[s].assign(N, {});
      for (int i = 0; i < M; ++i) {
        graph[s][A[i]].push_back(B[i]);
        graph[s][B[i]].push_back(A[i]);
      }
    }
    
    const auto scc = sccDyn(N << 1, [&](int s, int uu) -> int {
      const int u = uu >> 1;
      if ((uu & 1) != s) {
        // s = 0: u ==> not(v)
        int v = kdt[s].take(P[u][1], P[u][0], P[u][2] - W + 1, P[u][2], P[u][3] - H + 1, P[u][3]);
        if (!~v) return -1;
        if (u == v) {
          v = kdt[s].take(P[u][1], P[u][0], P[u][2] - W + 1, P[u][2], P[u][3] - H + 1, P[u][3]);
          kdt[s].restore(u);
          if (!~v) return -1;
        }
// cerr<<__LINE__<<": [get] "<<s<<" "<<u<<" "<<v<<"; "<<uu<<" "<<(v<<1|s)<<endl;
        return v << 1 | s;
      } else {
        // s = 0: not(u) ==> v
        if (!graph[s][u].size()) return -1;
        const int v = graph[s][u].back();
        graph[s][u].pop_back();
// cerr<<__LINE__<<": [get] "<<s<<" "<<u<<" "<<v<<"; "<<uu<<" "<<(v<<1|(s^1))<<endl;
        return v << 1 | (s ^ 1);
      }
    });
// cerr<<"scc = "<<scc.ids<<endl;
    
    bool ok = true;
    string ans(N, '?');
    for (int u = 0; u < N; ++u) {
      ok = ok && (scc[u << 1] != scc[u << 1 | 1]);
      ans[u] = (scc[u << 1] > scc[u << 1 | 1]) ? '1' : '0';
    }
    if (ok) {
      puts("Yes");
      puts(ans.c_str());
    } else {
      puts("No");
    }
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3940kb

input:

2 2 2
1 2 1 1
2 3 2 2
1
1 2

output:

Yes
10

result:

ok accepted

Test #2:

score: 0
Accepted
time: 0ms
memory: 3936kb

input:

3 2 2
1 2 1 1
1 3 1 2
2 3 2 2
3
1 2
2 3
1 3

output:

No

result:

ok accepted

Test #3:

score: -100
Wrong Answer
time: 0ms
memory: 3728kb

input:

10 3 3
2 3 7 10
1 3 9 6
3 5 2 1
4 5 8 9
4 7 1 7
3 4 4 4
6 8 9 5
1 3 6 7
2 5 7 4
6 9 9 9
10
9 1
6 2
8 5
9 5
10 4
5 1
3 2
10 9
9 5
8 2

output:

Yes
0101001000

result:

wrong answer both 9 and 1 are not chosen