(UPD: 2024-12-04 14:48 UTC) Judge is not working due to Cloudflare incident. (URL) We can do nothing about it, sorry. After the incident is resolved, we will grade all submissions.

Submission #834972

#TimeUsernameProblemLanguageResultExecution timeMemory
834972senthetaGarden (JOI23_garden)C++17
100 / 100
115 ms17728 KiB
#include<bits/stdc++.h> using namespace std; #define V vector #define rep(i,a,b) for(int i=(int)(a); i<(int)(b); i++) #define Int long long #define all(x) (x).begin(), (x).end() #if VANWIJ #define DBG 1 #else #define DBG 0 #endif #define cerr if(DBG) cout #define dbg(x) cerr << "?" << #x << " : " << x << endl; // van Emde Boas tree. Maintains a set of integers in range [0, 2^B) and supports operations // findNext(i): returns minimum j >= i in set, or 2^B if none exist // findPrev(i): returns maximum j <= i in set, or -1 if none exist // insert(i), erase(i): insert/erase i into the set // empty(): returns TRUE if the set is empty // clear(): empties the set // init(bts): inits the set, after the call i will be in the set if bts[i] = 1. bts should be a bitset, but can be a vector of 0/1 // All operations except empty, clear and init are O(log B) = O(log log 2^B) with good constants // example: VEBTree<17> s; // REMEMBER TO CALL s.clear() BEFORE USING // source : https://judge.yosupo.jp/submission/76699 #define ull unsigned long long template<int B, typename ENABLE = void> class VEBTree { private: const static int K = B/2, R = (B+1)/2, M = (1<<B); const static int S = 1<<K, MASK = (1<<R)-1; array<VEBTree<R>,S> ch; VEBTree<K> act; int mi, ma; public: bool empty() const{return ma<mi;} int findNext(int i) const{ if(i <= mi) return mi; if(i > ma) return M; int j = i>>R, x = i&MASK; int res = ch[j].findNext(x); if(res<=MASK) return (j<<R) + res; j=act.findNext(j + 1); return (j>=S) ? ma : ((j<<R) + ch[j].findNext(0)); } int findPrev(int i) const { if(i >= ma) return ma; if(i < mi) return -1; int j = i>>R, x = i & MASK; int res = ch[j].findPrev(x); if(res >= 0) return (j<<R) + res; j = act.findPrev(j - 1); return (j < 0) ? mi : ((j<<R) + ch[j].findPrev(MASK)); } void insert(int i) { if(i <= mi) { if(i == mi) return; swap(mi, i); if(i == M) ma = mi; // we were empty if(i >= ma) return; // we had mi == ma } else if(i >= ma) { if(i == ma) return; swap(ma, i); if(i <= mi) return; // we had mi == ma } int j = i>>R; if(ch[j].empty()) act.insert(j); ch[j].insert(i & MASK); } void erase(int i) { if(i <= mi) { if(i < mi) return; i = mi = findNext(mi + 1); if(i >= ma) { if(i > ma) ma = -1; // we had mi == ma return; // after erase we have mi == ma } } else if(i >= ma) { if(i > ma) return; i = ma = findPrev(ma - 1); if(i <= mi) return; // after erase we have mi == ma } int j = i>>R; ch[j].erase(i & MASK); if(ch[j].empty()) act.erase(j); } void clear() { mi = M, ma = -1; act.clear(); for (int i = 0; i < S; ++i) ch[i].clear(); } template<class T> void init(const T& bts, int shift = 0, int s0 = 0, int s1 = 0) { s0 = -shift + bts.findNext(shift + s0, shift + M-1 - s1); s1 = M-1 - (-shift + bts.findPrev(shift + M-1-s1, shift + s0)); if(s0 + s1 >= M) clear(); else { act.clear(); mi = s0, ma = M-1 - s1; ++s0; ++s1; for (int j = 0; j < S; ++j) { ch[j].init(bts, shift + (j<<R), max(0, s0 - (j<<R)), max(0, s1 - ((S-1-j)<<R))); if(! ch[j].empty()) act.insert(j); } } } }; template<int B> class VEBTree<B, enable_if_t<(B <= 6)>> { private: const static int M = (1<<B); ull act; public: bool empty() const { return !act; } void clear() { act = 0; } int findNext(int i) const { return ((i < M) && (act>>i)) ? i + __builtin_ctzll(act>>i) : M; } int findPrev(int i) const { return ((i != -1) && (act<<(63 - i))) ? i - __builtin_clzll(act<<(63 - i)) : -1; } void insert(int i) { act |= 1ull<<i; } void erase(int i) { act &= ~(1ull<<i); } template<class T> void init(const T& bts, int shift = 0, int s0 = 0, int s1 = 0) { if(s0 + s1 >= M) act = 0; else act = bts.getRange(shift + s0, shift + M-1-s1)<<s0; } }; const int INF = 1e9; const int N = 5e5+5; const int K = 5005; int n, m, k; V<int> a, b, c, d; V<int> byx[2*K]; int ans = INF; bool inside(int l,int x,int r){ return (l<=x && x<=r) || (l<=x+k && x+k<=r); } const int LK = 13; // set of must-have y's // set<int> s; VEBTree<LK> s; int cnt[K]; // set of gaps between must-have y // set<int> gaps; VEBTree<LK> gaps; int cntgaps[K]; void gap_insert(int val){ cntgaps[val]++; if(cntgaps[val]==1){ gaps.insert(val); } } void gap_erase(int val){ cntgaps[val]--; if(cntgaps[val]==0){ gaps.erase(val); } } void insert(int y){ cnt[y]++; if(cnt[y]!=1) return; int l=s.findPrev(y), r=s.findNext(y); s.insert(y); if(l!=-1 && r!=1LL<<LK){ gap_erase(r-l); } if(l!=-1){ gap_insert(y-l); } if(r!=1LL<<LK){ gap_insert(r-y); } } void erase(int y){ cnt[y]--; if(cnt[y]!=0) return; s.erase(y); int l=s.findPrev(y), r=s.findNext(y); if(l!=-1 && r!=1LL<<LK){ gap_insert(r-l); } if(l!=-1){ gap_erase(y-l); } if(r!=1LL<<LK){ gap_erase(r-y); } } // get optimal width int getWidth(){ int ret = k-gaps.findPrev((1LL<<LK)-1)+1; ret = min(ret, s.findPrev((1LL<<LK)-1)-s.findNext(0)+1); return ret; } int minimum_cells(int _n,int _m,int _k,V<int>_a,V<int>_b,V<int>_c,V<int>_d){ n = _n; m = _m; k = _k; a.swap(_a); b.swap(_b); c.swap(_c); d.swap(_d); // A[i] or B[i] // C[i] and D[i] // flip X and Y in second loop rep(loop,0,2){ s.clear(); gaps.clear(); rep(i,0,k){ cnt[i] = cntgaps[i] = 0; } // insert needed Y bool vx[k]; rep(i,0,k) vx[i] = 0; rep(i,0,n){ vx[a[i]] = 1; insert(b[i]); } rep(i,0,k){ byx[i].clear(); } rep(i,0,m){ byx[c[i]].push_back(i); } // cerr << "Y-GAP" << endl; // for(int y : s) cerr << y << " "; // cerr << endl; // for(int gap : gaps) cerr << gap << " "; // cerr << endl; // iterate all possible X gaps int first=-1, last=-1; rep(i,0,k) if(vx[i]){ if(first==-1) first = i; if(last!=-1){ // check(i, last+k); for(int x=(last+1)%k; x!=i; /*x=(x+1)%k*/){ for(int j : byx[x]) insert(d[j]); x++; if(x==k) x=0; } ans = min(ans, (k+last-i+1)*getWidth()); for(int x=(last+1)%k; x!=i; /*x=(x+1)%k*/){ for(int j : byx[x]) erase(d[j]); x++; if(x==k) x=0; } } last = i; } // check(first, last); for(int x=(last+1)%k; x!=first; x=(x+1)%k){ for(int j : byx[x]) insert(d[j]); } ans = min(ans, (last-first+1)*getWidth()); for(int x=(last+1)%k; x!=first; x=(x+1)%k){ for(int j : byx[x]) erase(d[j]); } a.swap(b); c.swap(d); } return ans; } int main() { int N, M, D; assert(3 == scanf("%d %d %d", &N, &M, &D)); std::vector<int> P(N), Q(N), R(M), S(M); for (int i = 0; i < N; ++i) { assert(2 == scanf("%d %d", &P[i], &Q[i])); } for (int j = 0; j < M; ++j) { assert(2 == scanf("%d %d", &R[j], &S[j])); } printf("%d\n", minimum_cells(N, M, D, P, Q, R, S)); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...