답안 #391712

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
391712 2021-04-19T15:19:14 Z usachevd0 저울 (IOI15_scales) C++14
100 / 100
149 ms 2440 KB
#include <bits/stdc++.h>
#ifndef DEBUG
  #include "scales.h"
#endif
 
using namespace std;
 
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(), (a).end()
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
using ld = long double;
template<typename T1, typename T2> bool chkmin(T1& x, T2 y) {
  return y < x ? (x = y, true) : false;
}
template<typename T1, typename T2> bool chkmax(T1& x, T2 y) {
  return y > x ? (x = y, true) : false;
}
void debug_out() {
  cerr << endl;
}
template<typename T1, typename... T2> void debug_out(T1 A, T2... B) {
  cerr << ' ' << A;
  debug_out(B...);
}
template<typename T> void mdebug_out(T* a, int n) {
  for (int i = 0; i < n; ++i) {
    cerr << a[i] << ' ';
  }
  cerr << endl;
}
#ifdef DEBUG
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
  #define mdebug(a, n) cerr << #a << ": ", mdebug_out(a, n)
#else
  #define debug(...) 1337
  #define mdebug(a, n) 1337
#endif
template<typename T> ostream& operator << (ostream& stream, const vector<T>& v) {
  for (auto& x : v) {
    stream << x << ' ';
  }
  return stream;
}
template<typename T1, typename T2> ostream& operator << (ostream& stream, const pair<T1, T2>& p) {
  return stream << p.first << ' ' << p.second;
}


#ifdef DEBUG
  vector<int> pp;
  vector<int> ip;
  int getHeaviest(int x, int y, int z) {
    vector<int> ord = {x, y, z};
    sort(all(ord), [&](int x, int y) -> bool {
      return ip[x] < ip[y];
    });
    return ord[2];
  }
  int getLightest(int x, int y, int z) {
    vector<int> ord = {x, y, z};
    sort(all(ord), [&](int x, int y) -> bool {
      return ip[x] < ip[y];
    });
    return ord[0];
  }
  int getMedian(int x, int y, int z) {
    vector<int> ord = {x, y, z};
    sort(all(ord), [&](int x, int y) -> bool {
      return ip[x] < ip[y];
    });
    return ord[1];
  }
  int getNextLightest(int x, int y, int z, int w) {
    vector<int> ord = {x, y, z};
    sort(all(ord), [&](int x, int y) -> bool {
      return ip[x] < ip[y];
    });
    int i = 0;
    while (i < 3 && ip[ord[i]] < ip[w]) ++i;
    return ord[i % 3];
  }
  void answer(int* p) {
    for (int i = 0; i < 6; ++i) {
      assert(pp[i] == p[i]);
    }
  }
#endif


int pw3[10];

const int P = 720;
const int Q = 120;
vector<int> perm[P];
map<vector<int>, int> pid;

using Mask = array<bool, P>;
Mask fullMask;

struct Query {
  int type;
  vector<int> args;

  Query() {}
  Query(int _type, int a, int b, int c) {
    type = _type;
    args = {a, b, c};
  }
  Query(int _type, int a, int b, int c, int d) {
    type = _type;
    args = {a, b, c, d};
  }
} query[Q];

int ans[P][Q];

void prec() {
  vector<int> p(6);
  iota(all(p), 0);
  int ptr = 0;
  do {
    perm[ptr++] = vector<int>(all(p));
  } while (next_permutation(all(p)));
  assert(ptr == P);

  ptr = 0;
  for (int a = 0; a < 6; ++a) {
    for (int b = a + 1; b < 6; ++b) {
      for (int c = b + 1; c < 6; ++c) {
        for (int type = 0; type <= 2; ++type) {
          query[ptr++] = Query(type, a, b, c);
        }
        for (int d = 0; d < 6; ++d) {
          if (d != a && d != b && d != c) {
            query[ptr++] = Query(3, a, b, c, d);
          }
        }
      }
    }
  }
  assert(ptr == Q);

  for (int pi = 0; pi < P; ++pi) {
    auto& p = perm[pi];
    vector<int> where(6);
    for (int i = 0; i < 6; ++i) {
      where[p[i]] = i;
    }
    for (int qi = 0; qi < Q; ++qi) {
      auto& q = query[qi];
      vector<pii> ord;
      for (int i = 0; i < 3; ++i) {
        ord.emplace_back(q.args[i], i);
      }
      sort(all(ord), [&](pii x, pii y) -> bool {
        return where[x.fi] < where[y.fi];
      });
      switch (q.type) {
        case 0:
          ans[pi][qi] = ord[2].se;
          break;
        case 1:
          ans[pi][qi] = ord[0].se;
          break;
        case 2:
          ans[pi][qi] = ord[1].se;
          break;
        case 3:
          int d = q.args[3];
          int i = 0;
          while (i < 3 && where[ord[i].fi] < where[d]) ++i;
          ans[pi][qi] = ord[i % 3].se;
          break;
      }
    }
  }

  pw3[0] = 1;
  for (int i = 1; i < 10; ++i) pw3[i] = pw3[i - 1] * 3;

  fill(all(fullMask), 1);
}

int Count(const Mask& mask) {
  return count(all(mask), 1);
}

map<pair<Mask, int>, bool> mem;
map<pair<Mask, int>, int> whatq;
bool brute(Mask mask, int rem = 6) {
  pair<Mask, int> key = {mask, rem};
  int cnt = Count(mask);
  if (cnt <= 1) {
    return mem[key] = true;
  }
  if (mem.count(key)) {
    return mem[key];
  }
  if (cnt > pw3[rem]) {
    return mem[key] = false;
  }
  for (int qi = 0; qi < Q; ++qi) {
    Mask nxt[3];
    for (int i = 0; i < 3; ++i) {
      fill(all(nxt[i]), 0);
    }
    for (int pi = 0; pi < P; ++pi) {
      if (mask[pi]) {
        nxt[ans[pi][qi]][pi] = 1;
      }
    }
    if (max(Count(nxt[0]), max(Count(nxt[1]), Count(nxt[2]))) <= pw3[rem - 1] && brute(nxt[0], rem - 1) && brute(nxt[1], rem - 1) && brute(nxt[2], rem - 1)) {
      whatq[key] = qi;
      return mem[key] = true;
    }
  }
  return mem[key] = false;
}



void init(int T) {
  prec();
  brute(fullMask, 6);
}

int ask(int qi) {
  auto& q = query[qi];
  switch (q.type) {
    case 0:
      return find(all(q.args), getHeaviest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      break;
    case 1:
      return find(all(q.args), getLightest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      break;
    case 2:
      return find(all(q.args), getMedian(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      break;
    case 3:
      return find(all(q.args), getNextLightest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1, q.args[3] + 1) - 1) - q.args.begin();
      break;
  }
}

void orderCoins() {
  Mask mask = fullMask;
  for (int rem = 6; rem > 0; --rem) {
    int qi = whatq[{mask, rem}];
    int r = ask(qi);
    for (int pi = 0; pi < P; ++pi) {
      mask[pi] &= ans[pi][qi] == r;
    }
  }
  int pi = 0;
  while (pi < P && !mask[pi]) ++pi;
  int p[6];
  for (int i = 0; i < 6; ++i) {
    p[i] = perm[pi][i] + 1;
  }
  answer(p);
} 
 
#ifdef DEBUG
int32_t main() {
#ifdef DEBUG
  freopen("in", "r", stdin);
#endif
  ios::sync_with_stdio(0);
  cin.tie(0);
 
  pp.resize(6);
  ip.resize(6);
  iota(all(pp), 0);
  init(-1);
  do {
    //debug(pp);
    for (int i = 0; i < 6; ++i) ip[pp[i]] = i;
    orderCoins();
  } while (next_permutation(all(pp)));
 
  return 0;
}
#endif

Compilation message

scales.cpp: In function 'void prec()':
scales.cpp:152:11: warning: declaration of 'p' shadows a previous local [-Wshadow]
  152 |     auto& p = perm[pi];
      |           ^
scales.cpp:126:15: note: shadowed declaration is here
  126 |   vector<int> p(6);
      |               ^
scales.cpp: In function 'int Count(const Mask&)':
scales.cpp:193:15: warning: conversion from 'std::iterator_traits<const bool*>::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  193 |   return count(all(mask), 1);
      |          ~~~~~^~~~~~~~~~~~~~
scales.cpp: In function 'void init(int)':
scales.cpp:230:15: warning: unused parameter 'T' [-Wunused-parameter]
  230 | void init(int T) {
      |           ~~~~^
scales.cpp: In function 'int ask(int)':
scales.cpp:239:94: warning: conversion from '__gnu_cxx::__normal_iterator<int*, std::vector<int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  239 |       return find(all(q.args), getHeaviest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
scales.cpp:242:94: warning: conversion from '__gnu_cxx::__normal_iterator<int*, std::vector<int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  242 |       return find(all(q.args), getLightest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
scales.cpp:245:92: warning: conversion from '__gnu_cxx::__normal_iterator<int*, std::vector<int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  245 |       return find(all(q.args), getMedian(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1) - 1) - q.args.begin();
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
scales.cpp:248:113: warning: conversion from '__gnu_cxx::__normal_iterator<int*, std::vector<int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  248 |       return find(all(q.args), getNextLightest(q.args[0] + 1, q.args[1] + 1, q.args[2] + 1, q.args[3] + 1) - 1) - q.args.begin();
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
scales.cpp:251:1: warning: control reaches end of non-void function [-Wreturn-type]
  251 | }
      | ^
# 결과 실행 시간 메모리 Grader output
1 Correct 108 ms 2296 KB Output is correct
2 Correct 112 ms 2424 KB Output is correct
3 Correct 108 ms 2320 KB Output is correct
4 Correct 112 ms 2244 KB Output is correct
5 Correct 126 ms 2240 KB Output is correct
6 Correct 149 ms 2244 KB Output is correct
7 Correct 109 ms 2240 KB Output is correct
8 Correct 108 ms 2236 KB Output is correct
9 Correct 112 ms 2440 KB Output is correct
10 Correct 108 ms 2224 KB Output is correct
11 Correct 112 ms 2292 KB Output is correct
12 Correct 141 ms 2228 KB Output is correct
13 Correct 109 ms 2324 KB Output is correct
14 Correct 108 ms 2340 KB Output is correct
15 Correct 108 ms 2428 KB Output is correct
16 Correct 117 ms 2260 KB Output is correct
17 Correct 108 ms 2340 KB Output is correct
18 Correct 108 ms 2268 KB Output is correct
19 Correct 108 ms 2328 KB Output is correct
20 Correct 113 ms 2244 KB Output is correct
21 Correct 109 ms 2348 KB Output is correct
22 Correct 109 ms 2320 KB Output is correct
23 Correct 112 ms 2292 KB Output is correct
24 Correct 107 ms 2224 KB Output is correct
25 Correct 113 ms 2340 KB Output is correct
26 Correct 110 ms 2344 KB Output is correct
27 Correct 108 ms 2384 KB Output is correct
28 Correct 108 ms 2400 KB Output is correct
29 Correct 116 ms 2244 KB Output is correct
30 Correct 112 ms 2260 KB Output is correct
31 Correct 109 ms 2224 KB Output is correct
32 Correct 107 ms 2292 KB Output is correct
33 Correct 108 ms 2332 KB Output is correct
34 Correct 115 ms 2272 KB Output is correct
35 Correct 113 ms 2376 KB Output is correct
36 Correct 107 ms 2220 KB Output is correct
37 Correct 107 ms 2224 KB Output is correct
38 Correct 111 ms 2344 KB Output is correct
39 Correct 109 ms 2256 KB Output is correct
40 Correct 129 ms 2332 KB Output is correct