Submission #333847

#TimeUsernameProblemLanguageResultExecution timeMemory
333847jc713Demarcation (BOI14_demarcation)C++17
100 / 100
173 ms18316 KiB
#include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/assoc_container.hpp> #include <bits/stdc++.h> using namespace std; using namespace __gnu_pbds; template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; using ll = long long; using ull = unsigned long long; using ld = long double; using db = double; using str = string; // yay python! using pi = pair<int,int>; using pl = pair<ll,ll>; using pd = pair<db,db>; using vi = vector<int>; using vb = vector<bool>; using vl = vector<ll>; using vd = vector<db>; using vs = vector<str>; using vpi = vector<pi>; using vpl = vector<pl>; using vpd = vector<pd>; #define tcT template<class T // ^ lol this makes everything look weird but I'll try it tcT> using V = vector<T>; tcT, size_t SZ> using AR = array<T,SZ>; // pairs #define mp make_pair #define f first #define s second // vectors #define sz(x) (int)(x).size() #define all(x) begin(x), end(x) #define rall(x) (x).rbegin(), (x).rend() #define sor(x) sort(all(x)) #define rsz resize #define ins insert #define ft front() #define bk back() #define pf push_front #define pb push_back #define eb emplace_back #define lb lower_bound #define ub upper_bound // loops #define FOR(i,a,b) for (int i = (a); i < (b); ++i) #define F0R(i,a) FOR(i,0,a) #define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i) #define R0F(i,a) ROF(i,0,a) #define trav(a,x) for (auto& a: x) const int MOD = 1e9+7; // 998244353 const int MX = 2e5+5; const ll INF = 1e18; // not too close to LLONG_MAX const int IINF = 1e9; const ld PI = acos((ld)-1); const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1}; // for every grid problem!! mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); // helper funcs constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set constexpr int bits(int x) { return 31-__builtin_clz(x); } // floor(log2(x)) ll cdiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } // divide a by b rounded up ll fdiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // divide a by b rounded down tcT> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; } // set a = min(a,b) tcT> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } #define tcTU tcT, class U tcTU> T fstTrue(T lo, T hi, U f) { hi ++; assert(lo <= hi); // assuming f is increasing while (lo < hi) { // find first index such that f is true T mid = lo+(hi-lo)/2; f(mid) ? hi = mid : lo = mid+1; } return lo; } tcTU> T lstTrue(T lo, T hi, U f) { lo --; assert(lo <= hi); // assuming f is decreasing while (lo < hi) { // find first index such that f is true T mid = lo+(hi-lo+1)/2; f(mid) ? lo = mid : hi = mid-1; } return lo; } tcT> void remDup(vector<T>& v) { // sort and remove duplicates sort(all(v)); v.erase(unique(all(v)),end(v)); } tcTU> void erase(T& t, const U& u) { // don't erase auto it = t.find(u); assert(it != end(t)); t.erase(u); } // element that doesn't exist from (multi)set // INPUT #define tcTUU tcT, class ...U tcT> void re(complex<T>& c); tcTU> void re(pair<T,U>& p); tcT> void re(vector<T>& v); tcT, size_t SZ> void re(AR<T,SZ>& a); tcT> void re(T& x) { cin >> x; } void re(db& d) { str t; re(t); d = stod(t); } void re(ld& d) { str t; re(t); d = stold(t); } tcTUU> void re(T& t, U&... u) { re(t); re(u...); } tcT> void re(complex<T>& c) { T a,b; re(a,b); c = {a,b}; } tcTU> void re(pair<T,U>& p) { re(p.f,p.s); } tcT> void re(vector<T>& x) { trav(a,x) re(a); } tcT, size_t SZ> void re(AR<T,SZ>& x) { trav(a,x) re(a); } // TO_STRING #define ts to_string str ts(char c) { return str(1,c); } str ts(const char* s) { return (str)s; } str ts(str s) { return s; } str ts(bool b) { #ifdef LOCAL return b ? "true" : "false"; #else return ts((int)b); #endif } tcT> str ts(complex<T> c) { stringstream ss; ss << c; return ss.str(); } str ts(vector<bool> v) { str res = "{"; F0R(i,sz(v)) res += char('0'+v[i]); res += "}"; return res; } template<size_t SZ> str ts(bitset<SZ> b) { str res = ""; F0R(i,SZ) res += char('0'+b[i]); return res; } tcTU> str ts(pair<T,U> p); tcT> str ts(T v) { // containers with begin(), end() #ifdef LOCAL bool fst = 1; str res = "{"; for (const auto& x: v) { if (!fst) res += ", "; fst = 0; res += ts(x); } res += "}"; return res; #else bool fst = 1; str res = ""; for (const auto& x: v) { if (!fst) res += " "; fst = 0; res += ts(x); } return res; #endif } tcTU> str ts(pair<T,U> p) { #ifdef LOCAL return "("+ts(p.f)+", "+ts(p.s)+")"; #else return ts(p.f)+" "+ts(p.s); #endif } // OUTPUT tcT> void pr(T x) { cout << ts(x); } tcTUU> void pr(const T& t, const U&... u) { pr(t); pr(u...); } void ps() { pr("\n"); } // print w/ spaces tcTUU> void ps(const T& t, const U&... u) { pr(t); if (sizeof...(u)) pr(" "); ps(u...); } // DEBUG void DBG() { cerr << "]" << endl; } tcTUU> void DBG(const T& t, const U&... u) { cerr << ts(t); if (sizeof...(u)) cerr << ", "; DBG(u...); } #ifdef LOCAL // compile with -DLOCAL, chk -> fake assert #define dbg(...) cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__) #define chk(...) if (!(__VA_ARGS__)) cerr << "Line(" << __LINE__ << ") -> function(" \ << __FUNCTION__ << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", exit(0); #else #define dbg(...) 0 #define chk(...) 0 #endif // FILE I/O void setIn(str s) { freopen(s.c_str(),"r",stdin); } void setOut(str s) { freopen(s.c_str(),"w",stdout); } void unsyncIO() { cin.tie(0)->sync_with_stdio(0); } void setIO(str s = "") { unsyncIO(); // cin.exceptions(cin.failbit); // throws exception when do smth illegal // ex. try to read letter into int if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO } struct custom_hash { static uint64_t splitmix64(uint64_t x) { // http://xorshift.di.unimi.it/splitmix64.c x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; int N; ll PERM = 0; void shift(vpl& p){ pl poi = mp(INF, INF); trav(a, p) ckmin(poi, a); trav(a, p) a = mp(a.f - poi.f, a.s - poi.s); } void rotate(vpl& p){ vpl ret; trav(a, p) ret.pb(mp(a.s, -a.f)); p = ret; } void reflect(vpl& p){ vpl ret; trav(a, p) ret.pb(mp(a.f, -a.s)); p = ret; } bool equiv(vpl& A, vpl& B){ set<pl> con; trav(a, A) con.insert(a); trav(a, B) if(con.count(a) == 0) return false; return (sz(A) == sz(B)); } bool check(vpl& A, vpl& B){ shift(A); shift(B); F0R(i, 4){ rotate(A); shift(A); if(equiv(A, B)) return true; } reflect(A); F0R(i, 4){ rotate(A); shift(A); if(equiv(A, B)) return true; } return false; } set<pair<pl, pl>> s; map<pair<pl, pl>, pi> ind; bool flip; bool solve(vpl p){ ll dist = 0; int i = 0; s.clear(); ind.clear(); F0R(a, sz(p)){ while(i < sz(p)){ if(dist + abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f) >= PERM / 2) break; dist += abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f); i++; } if(i == sz(p)) break; while(i < sz(p)){ pair<pl, pl> x = mp(p[a], p[(a + 1) % N]); pair<pl, pl> y = mp(p[i], p[(i + 1) % N]); if(x.f.s == x.s.s && y.f.s == y.s.s){ if((x.f.f > x.s.f) != (y.f.f > y.s.f)){ if(y.f.f > y.s.f){ ll init = y.f.f - (PERM / 2 - dist); if((init - x.f.f) % 2 == 0 && (init + x.f.f) / 2 >= x.f.f && (init + x.f.f) / 2 <= y.f.f && (init + x.f.f) / 2 <= x.s.f && (init + x.f.f) / 2 >= y.s.f) s.insert(mp(mp((init + x.f.f) / 2, min(x.f.s, y.f.s)), mp((init + x.f.f) / 2, max(x.f.s, y.f.s)))); } else{ ll init = y.f.f + (PERM / 2 - dist); if((x.f.f - init) % 2 == 0 && (init + x.f.f) / 2 <= x.f.f && (init + x.f.f) / 2 >= y.f.f && (init + x.f.f) / 2 >= x.s.f && (init + x.f.f) / 2 <= y.s.f) s.insert(mp(mp((init + x.f.f) / 2, min(x.f.s, y.f.s)), mp((init + x.f.f) / 2, max(x.f.s, y.f.s)))); } } } if(dist + abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f) >= PERM / 2 + abs(p[(a + 1) % N].s - p[a].s + p[(a + 1) % N].f - p[a].f)) break; dist += abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f); i++; } if(i < sz(p)){ pair<pl, pl> x = mp(p[a], p[(a + 1) % N]); pair<pl, pl> y = mp(p[(i + 1) % N], p[(i + 2) % N]); if(x.f.s == x.s.s && y.f.s == y.s.s){ if((x.f.f > x.s.f) != (y.f.f > y.s.f)){ if(y.f.f > y.s.f){ ll init = y.f.f - (PERM / 2 - dist - abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f)); if((init - x.f.f) % 2 == 0 && (init + x.f.f) / 2 >= x.f.f && (init + x.f.f) / 2 <= y.f.f && (init + x.f.f) / 2 <= x.s.f && (init + x.f.f) / 2 >= y.s.f) s.insert(mp(mp((init + x.f.f) / 2, min(x.f.s, y.f.s)), mp((init + x.f.f) / 2, max(x.f.s, y.f.s)))); } else{ ll init = y.f.f + (PERM / 2 - dist - abs(p[(i + 1) % N].s - p[i].s + p[(i + 1) % N].f - p[i].f)); if((x.f.f - init) % 2 == 0 && (init + x.f.f) / 2 <= x.f.f && (init + x.f.f) / 2 >= y.f.f && (init + x.f.f) / 2 >= x.s.f && (init + x.f.f) / 2 <= y.s.f) s.insert(mp(mp((init + x.f.f) / 2, min(x.f.s, y.f.s)), mp((init + x.f.f) / 2, max(x.f.s, y.f.s)))); } } } } dist -= abs(p[(a + 1) % N].s - p[a].s + p[(a + 1) % N].f - p[a].f); }//true = start priority_queue<pair<pair<ll, bool>, ll>, vector<pair<pair<ll, bool>, ll>>, greater<pair<pair<ll, bool>, ll>>> Q; F0R(a, sz(p)){ pair<pl, pl> temp = mp(p[a], p[(a + 1) % N]); if(temp.f.s == temp.s.s){ if(temp.f > temp.s) swap(temp.f, temp.s); Q.push(mp(mp(temp.f.f, false), temp.s.s)); Q.push(mp(mp(temp.s.f, true), temp.s.s)); } } Tree<int> c2; trav(e, s){ bool good = false; while(sz(Q) && Q.top().f.f < e.f.f){ auto temp = Q.top(); Q.pop(); if(temp.f.s == false) c2.insert(temp.s); else c2.erase(temp.s); } while(sz(Q) && Q.top().f.f == e.f.f && Q.top().f.s == false){ auto t2 = Q.top(); Q.pop(); c2.insert(t2.s); } int V1 = c2.order_of_key(e.f.s), V2 = c2.order_of_key(e.s.s); if(V1 == V2 - 1) good = true; if(good){ vpl A1, A; vpl B1, B; int fst = -1; int sec = -1; F0R(a, sz(p)){ if(p[a].s == p[(a + 1) % N].s && p[a].s == e.f.s){ if(min(p[a].f, p[(a + 1) % N].f) <= e.f.f && max(p[a].f, p[(a + 1) % N].f) >= e.f.f){ fst = a; break; } } } F0R(a, sz(p)){ if(p[a].s == p[(a + 1) % N].s && p[a].s == e.s.s){ if(min(p[a].f, p[(a + 1) % N].f) <= e.s.f && max(p[a].f, p[(a + 1) % N].f) >= e.s.f){ sec = a; break; } } } A1.pb(e.f); for(int a = (fst + 1) % N;;a = (a + 1) % N){ A1.pb(p[a]); if(a == sec) break; } A1.pb(e.s); B1.pb(e.s); for(int a = (sec + 1) % N;;a = (a + 1) % N){ B1.pb(p[a]); if(a == fst) break; } B1.pb(e.f); A1.erase(unique(all(A1)), A1.end()); B1.erase(unique(all(B1)), B1.end()); F0R(a, sz(A1)){ if((A1[a].f == A1[(a + 1) % sz(A1)].f && A1[a].s != A1[(a + 1) % sz(A1)].s && A1[(a + 1) % sz(A1)].f != A1[(a + 2) % sz(A1)].f && A1[(a + 1) % sz(A1)].s == A1[(a + 2) % sz(A1)].s) || (A1[a].f != A1[(a + 1) % sz(A1)].f && A1[a].s == A1[(a + 1) % sz(A1)].s && A1[(a + 1) % sz(A1)].f == A1[(a + 2) % sz(A1)].f && A1[(a + 1) % sz(A1)].s != A1[(a + 2) % sz(A1)].s)){ A.pb(A1[(a + 1) % sz(A1)]); } } F0R(a, sz(B1)){ if((B1[a].f == B1[(a + 1) % sz(B1)].f && B1[a].s != B1[(a + 1) % sz(B1)].s && B1[(a + 1) % sz(B1)].f != B1[(a + 2) % sz(B1)].f && B1[(a + 1) % sz(B1)].s == B1[(a + 2) % sz(B1)].s) || (B1[a].f != B1[(a + 1) % sz(B1)].f && B1[a].s == B1[(a + 1) % sz(B1)].s && B1[(a + 1) % sz(B1)].f == B1[(a + 2) % sz(B1)].f && B1[(a + 1) % sz(B1)].s != B1[(a + 2) % sz(B1)].s)){ B.pb(B1[(a + 1) % sz(B1)]); } } bool found = check(A, B); if(found){ if(!flip) cout << e.f.f << " " << e.f.s << " " << e.s.f << " " << e.s.s << endl; else cout << e.f.s << " " << e.f.f << " " << e.s.s << " " << e.s.f << endl; return true; } return false; } } return false; } int main(){ setIO(); cin >> N; vpl poly(N); F0R(a, N) cin >> poly[a].f >> poly[a].s; F0R(a, N) PERM += abs(poly[(a + 1) % N].f - poly[a].f) + abs(poly[(a + 1) % N].s - poly[a].s); if(PERM % 2 == 1){ cout << "NO" << endl; return 0; } if(solve(poly)) return 0; F0R(a, N) swap(poly[a].f, poly[a].s); flip = true; if(!solve(poly)) cout << "NO" << endl; // you should actually read the stuff at the bottom } /* stuff you should look for * int overflow, array bounds * special cases (n=1?) * do smth instead of nothing and stay organized * WRITE STUFF DOWN * DON'T GET STUCK ON ONE APPROACH */

Compilation message (stderr)

demarcation.cpp: In function 'void setIn(str)':
demarcation.cpp:190:28: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
  190 | void setIn(str s) { freopen(s.c_str(),"r",stdin); }
      |                     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
demarcation.cpp: In function 'void setOut(str)':
demarcation.cpp:191:29: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
  191 | void setOut(str s) { freopen(s.c_str(),"w",stdout); }
      |                      ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...