Submission #985959

#TimeUsernameProblemLanguageResultExecution timeMemory
985959MateiKing80Werewolf (IOI18_werewolf)C++14
100 / 100
848 ms125500 KiB
#include <bits/stdc++.h> #include "werewolf.h" using namespace std; #define all(a) (a).begin(), (a).end() const int NMAX = 2e5, MMAX = 4e5; vector<int> vec[NMAX + 5]; struct DSU { int n; vector<int> papa; DSU(int N) { papa.resize(N + 1); for(int i = 1; i <= N; i ++) papa[i] = i; n = N; } int real_papa(int nod) { if(papa[nod] == nod) return nod; return papa[nod] = real_papa(papa[nod]); } bool query(int u, int v) { return real_papa(u) == real_papa(v); } void join(int u, int v) { papa[real_papa(v)] = real_papa(u); } }; struct Arbore { vector<int> adanc; vector<vector<int>> lift, vec; int n, bitMax, root; Arbore(int N, int ROOT) { n = N; vec.resize(N + 1); bitMax = 20; root = ROOT; } void add_edge(int u, int v) { vec[u].push_back(v); vec[v].push_back(u); } void dfs_lca(int nod, int papa) { lift[0][nod] = papa; adanc[nod] = adanc[papa] + 1; for(auto i : vec[nod]) if(i != papa) dfs_lca(i, nod); } void make_lca() { lift.resize(bitMax, vector<int> (n + 1)); adanc.resize(n + 1, 0); dfs_lca(root, 0); for(int i = 1; i < bitMax; i ++) for(int j = 1; j <= n; j ++) lift[i][j] = lift[i - 1][lift[i - 1][j]]; } int findSmallestBigger(int u, int val) { int bit = bitMax - 1; while(bit >= 0) { if(lift[bit][u] >= val) u = lift[bit][u]; bit --; } return u; } int findBiggestSmaller(int u, int val) { int bit = bitMax - 1; while(bit >= 0) { if(lift[bit][u] <= val && lift[bit][u] != 0) u = lift[bit][u]; bit --; } return u; } void dfs_order(int nod, int papa, vector<int> &ord, vector<pair<int, int>> &subTree) { ord.push_back(nod); subTree[nod].first = ord.size() - 1; for(auto i : vec[nod]) if(i != papa) dfs_order(i, nod, ord, subTree); subTree[nod].second = ord.size() - 1; } vector<pair<int, int>> preOrder() { vector<int> ord(1, 0); vector<pair<int, int>> subTree(n + n); dfs_order(root, 0, ord, subTree); return subTree; } }; struct Fenwick { vector<int> aib; int n; Fenwick(int N) { n = N; aib.resize(N + 1); } inline int lsb(int x) { return x & -x; } void update(int pos, int val) { while(pos <= n) { aib[pos] += val; pos += lsb(pos); } } int query(int pos) { int ans = 0; while(pos) { ans += aib[pos]; pos -= lsb(pos); } return ans; } }; struct ura { int pos, val, index, inm; }; bool operator < (ura a, ura b) { return a.val < b.val; } vector<int> check_validity(int n, vector<int> u, vector<int> v, vector<int> s, vector<int> f, vector<int> l, vector<int> r) { int m = u.size(), q = s.size(); vector<vector<int>> vec(n + 1); for(int i = 0; i < m; i ++) vec[u[i] + 1].push_back(v[i] + 1), vec[v[i] + 1].push_back(u[i] + 1); for(int i = 0; i < q; i ++) s[i] ++, f[i] ++, l[i] ++, r[i] ++; DSU dsuOm(n), dsuLup(n); Arbore om(n, 1), lup(n, n); for(int i = n; i; i --) { for(auto j : vec[i]) if(j >= i && !dsuOm.query(i, j)) { om.add_edge(dsuOm.real_papa(i), dsuOm.real_papa(j)); dsuOm.join(i, j); } } for(int i = 1; i <= n; i ++) { for(auto j : vec[i]) if(j <= i && !dsuLup.query(i, j)) { lup.add_edge(dsuLup.real_papa(i), dsuLup.real_papa(j)); dsuLup.join(i, j); } } om.make_lca(), lup.make_lca(); auto ordOm = om.preOrder(), ordLup = lup.preOrder(); vector<int> ans(q), posLupSchimbat(n + 1); Fenwick aib(n); for(int i = 1; i <= n; i ++) posLupSchimbat[ordOm[i].first] = ordLup[i].first; vector<ura> aux; for(int i = 0; i < q; i ++) { if(s[i] < l[i] || f[i] > r[i]) continue; //cout << s[i] << " " << l[i] << '\n' << f[i] << " " << r[i] << '\n'; l[i] = om.findSmallestBigger(s[i], l[i]); r[i] = lup.findBiggestSmaller(f[i], r[i]); //cout << l[i] << " " << r[i] << '\n'; aux.push_back({ordLup[r[i]].second, ordOm[l[i]].second, i, 1}); aux.push_back({ordLup[r[i]].second, ordOm[l[i]].first - 1, i, -1}); aux.push_back({ordLup[r[i]].first - 1, ordOm[l[i]].second, i, -1}); aux.push_back({ordLup[r[i]].first - 1, ordOm[l[i]].first - 1, i, 1}); } sort(all(aux)); int p = 0; for(int i = 0; i <= n; i ++) { while(p < aux.size() && aux[p].val == i) ans[aux[p].index] += aib.query(aux[p].pos) * aux[p].inm, p ++; if(i != n) aib.update(posLupSchimbat[i + 1], 1); } for(int i = 0; i < q; i ++) ans[i] = ans[i] != 0; return ans; } void dfs_mai_mare(int nod, int l, vector<vector<int>> &vec, vector<bool> &viz) { if(viz[nod] || nod < l) return; viz[nod] = true; for(auto i : vec[nod]) dfs_mai_mare(i, l, vec, viz); } void dfs_mai_mic(int nod, int r, vector<vector<int>> &vec, vector<bool> &viz) { if(viz[nod] || nod > r) return; viz[nod] = true; for(auto i : vec[nod]) dfs_mai_mic(i, r, vec, viz); } vector<int> check_validity_prost(int n, vector<int> u, vector<int> v, vector<int> s, vector<int> f, vector<int> l, vector<int> r) { vector<vector<int>> vec(n); for(int i = 0; i < u.size(); i ++) vec[u[i]].push_back(v[i]), vec[v[i]].push_back(u[i]); vector<int> ans; for(int i = 0; i < s.size(); i ++) { ans.push_back(0); vector<bool> viz1(n, false), viz2(n, false); dfs_mai_mare(s[i], l[i], vec, viz1); dfs_mai_mic(f[i], r[i], vec, viz2); for(int i = 0; i < n; i ++) if(viz1[i] == 1 && viz2[i] == 1) ans.back() = 1; } return ans; } mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int rrng(int l, int r) { return rng() % (r - l + 1) + l; } /* bool generate_test() { int n = rrng(5, 10); set<pair<int, int>> se; vector<int> ord; for(int i = 0; i < n; i ++) ord.push_back(i); shuffle(all(ord), rng); int m = rrng(n, n + 5), q = 10; vector<int> u, v, s, f, l, r; for(int i = 1; i < n; i ++) { u.push_back(i); v.push_back(rrng(0, i - 1)); se.insert({v.back(), u.back()}); } for(int i = n - 1; i < m; i ++) { while(1) { int x = rrng(0, n - 1), y = rrng(0, n - 1); if(x > y) swap(x, y); if(x == y || se.count({x, y})) continue; se.insert({x, y}); v.push_back(x); u.push_back(y); break; } } for(int i = 0; i < m; i ++) if(rrng(0, 1)) swap(u[i], v[i]); for(int i = 0; i < q; i ++) { while(1) { int start = rrng(0, n - 1), finish = rrng(0, n - 1), ll = rrng(0, n - 1), rr = rrng(0, n - 1); if(ll > rr) swap(ll, rr); if(start == finish || ll == rr) continue; s.push_back(start); f.push_back(finish); l.push_back(ll); r.push_back(rr); break; } } if(check_validity_prost(n, u, v, s, f, l, r) == check_validity_smart(n, u, v, s, f, l, r)) return true; cout << n << " " << m << " " << q << '\n'; for(int i = 0; i < m; i ++) cout << u[i] << " " << v[i] << '\n'; for(int i = 0; i < q; i ++) cout << s[i] << " " << f[i] << " " << l[i] << " " << r[i] << '\n'; auto x = check_validity_prost(n, u, v, s, f, l, r), y = check_validity_smart(n, u, v, s, f, l, r); for(auto i : x) cout << i << " "; cout << '\n'; for(auto j : y) cout << j << " "; cout << '\n'; return false; } int main() { int t; cin >> t; for(int i = 1; i <= t; i ++) { cout << i << '\n'; if(!generate_test()) break; } }*/ /* 5 5 1 1 0 2 0 3 1 4 3 1 4 4 3 2 4 */ /* 5 5 10 1 0 2 0 3 1 4 3 1 4 1 3 0 3 1 3 0 4 3 1 1 2 4 3 2 4 4 2 1 4 0 3 2 3 4 0 2 4 2 4 0 1 3 4 3 4 0 4 2 4 1 1 1 1 1 0 1 0 1 0 1 1 1 0 1 0 0 0 1 0 */

Compilation message (stderr)

werewolf.cpp: In function 'std::vector<int> check_validity(int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
werewolf.cpp:231:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<ura>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  231 |         while(p < aux.size() && aux[p].val == i)
      |               ~~^~~~~~~~~~~~
werewolf.cpp: In function 'std::vector<int> check_validity_prost(int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
werewolf.cpp:264:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  264 |     for(int i = 0; i < u.size(); i ++)
      |                    ~~^~~~~~~~~~
werewolf.cpp:267:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  267 |     for(int i = 0; i < s.size(); i ++)
      |                    ~~^~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...