Submission #155184

#TimeUsernameProblemLanguageResultExecution timeMemory
155184rama_pangWerewolf (IOI18_werewolf)C++14
0 / 100
941 ms129680 KiB
#include "werewolf.h" #include <bits/stdc++.h> using namespace std; struct disj { vector<int> p; disj(int n) { p.resize(n); iota(p.begin(), p.end(), 0); } int par(int n) { return (p[n] == n)? n : p[n] = par(p[n]); } }; struct graph { vector<vector<int>> G; graph(int n) { G.resize(n); } inline void add_edge(int a, int b) { G[a].emplace_back(b); } void dfs(int n, int p, vector<pair<int, int>> &euler_tour, vector<int> &euler) { euler_tour[n].first = euler.size(); euler.emplace_back(n); for (auto &i : G[n]) if (i != p) { dfs(i, n, euler_tour, euler); } euler_tour[n].second = euler.size() - 1; } }; struct solver { struct event { int x, y1, y2, type, idx; bool operator < (const event &b) const { return x < b.x || (x == b.x && type < b.type); } }; struct bit { vector<int> tree; bit() {} bit(int n) { tree.resize(n + 1); } void init(int n) { tree.assign(n + 1, 0); } void upd(int n, int x) { for (int i = n + 1; i < tree.size(); i += i & -i) { tree[i] += x; } } int ask(int n) { int res = 0; for (int i = n + 1; i > 0; i -= i & -i) { res += tree[i]; } return res; } }; vector<event> e; bit bt; solver(int n) { bt.init(n); } inline void add_point(int x, int y) { e.push_back({x, y, -1, 0, -1}); //add point } inline void add_query(int x1, int x2, int y1, int y2, int id) { e.push_back({x1, y1, y2, -1, id}); //add e.push_back({x2, y1, y2, +1, id}); //remove } void line_sweep(vector<int> &res) { sort(e.begin(), e.end()); for (auto &k : e) { if (k.type == -1) { res[k.idx] -= bt.ask(k.y2) - bt.ask(k.y1 - 1); } else if (k.type == 0) { bt.upd(k.y1, 1); } else { res[k.idx] += bt.ask(k.y2) - bt.ask(k.y1 - 1); } } } }; vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) { int M = X.size(), Q = S.size(); /* create a rooted tree, such that any node u can reach its subtrees for L and R */ disj dsL(N), dsR(N); graph lowerL(N), upperR(N); vector<vector<int>> pending_edgeL(N), pending_edgeR(N); vector<vector<int>> binary_liftL(N, vector<int>(20, -1)), binary_liftR(N, vector<int>(20, -1)); for (int i = 0; i < M; i++) { if (X[i] > Y[i]) swap(X[i], Y[i]); pending_edgeL[X[i]].emplace_back(Y[i]); pending_edgeR[Y[i]].emplace_back(X[i]); } /* build tree for L, iterating high vertices first (most limited if L is high) */ for (int i = N - 1; i >= 0; i--) { for (auto &j : pending_edgeL[i]) { int p = dsL.par(j); if (i == p) continue; dsL.p[p] = i; binary_liftL[p][0] = i; lowerL.add_edge(i, p); } } /* do the same for tree R */ for (int i = 0; i < N; i++) { for (auto &j : pending_edgeR[i]) { int p = dsR.par(j); if (i == p) continue; dsR.p[p] = i; binary_liftR[p][0] = i; upperR.add_edge(i, p); } } // cout << "GOT HERE" << endl; /* create binary lifting for each query S and E, find minimum from S and maximum from E (vertex number) */ for (int j = 1; j < 20; j++) { for (int i = 0; i < N; i++) { if (binary_liftL[i][j - 1] != -1) binary_liftL[i][j] = binary_liftL[binary_liftL[i][j - 1]][j - 1]; if (binary_liftR[i][j - 1] != -1) binary_liftR[i][j] = binary_liftR[binary_liftR[i][j - 1]][j - 1]; } } // cout << "GOT HERE" << endl; /* create euler tour -> represent the graph with intervals */ vector<pair<int, int>> intervalL(N), intervalR(N); vector<int> eulerL, eulerR; lowerL.dfs(0, -1, intervalL, eulerL); upperR.dfs(N - 1, -1, intervalR, eulerR); /* get index of intervalR */ vector<int> other_name(N); for (int i = 0; i < N; i++) { other_name[eulerL[i]] = i; //map eulerL to 0...(N - 1) } // cout << "GOT HERE" << endl; /* fenwick tree + line sweep technique to solve, decompose if (intervalL[i] == intervalR[j]) add point (i, j), then check for rectangle for each query */ solver Solver(N); for (int i = 0; i < N; i++) { Solver.add_point(i, other_name[eulerR[i]]); //apply the same mapping to eulerR } // cout << "GOT HERE" << endl; for (int i = 0; i < Q; i++) { //get updates, lift S and E with binary lifting int s = S[i], e = E[i]; for (int j = 20; j >= 0; j--) { //binary lifting if (binary_liftL[s][j] != -1 && L[i] <= binary_liftL[s][j]) s = binary_liftL[s][j]; if (binary_liftL[e][j] != -1 && binary_liftL[e][j] <= R[i]) e = binary_liftL[e][j]; } Solver.add_query(intervalL[s].first, intervalL[s].second, intervalR[i].first, intervalR[i].second, i); } // cout << "GOT HERE" << endl; vector<int> res(Q); Solver.line_sweep(res); for (int i = 0; i < Q; i++) { res[i] = (res[i] > 0); } return res; } /* 6 6 3 5 1 1 2 1 3 3 4 3 0 5 2 4 2 1 2 4 2 2 2 5 4 3 4 */

Compilation message (stderr)

werewolf.cpp: In member function 'void solver::bit::upd(int, int)':
werewolf.cpp:52:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
             for (int i = n + 1; i < tree.size(); i += i & -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...