Submission #427861

#TimeUsernameProblemLanguageResultExecution timeMemory
427861amoo_safarIOI Fever (JOI21_fever)C++17
100 / 100
2466 ms417708 KiB
#include<bits/stdc++.h> #define F first #define S second #define pb push_back #define all(x) x.begin(), x.end() #define debug(x) cerr << #x << " : " << x << '\n' // #define int long long using namespace std; typedef pair<int, int> pii; const int N = 1e5 + 10; const int Inf = 1'000'000'010; int n; int x[N], y[N]; int dir[N]; pii vec[] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}}; set< pair<int, int> > st; // time, id int mk[N]; set<pair<int, int> > vis; int Collision(int a, int b){ if(x[a] > x[b]) swap(a, b); if(x[a] == x[b]){ if(y[a] > y[b]) swap(a, b); if(dir[a] == 3 && dir[b] == 1) return abs(y[a] - y[b]) / 2; return Inf; } if(y[a] == y[b]){ // if(y[a] > y[b]) swap(a, b); if(dir[a] == 0 && dir[b] == 2) return abs(x[a] - x[b]) / 2; return Inf; } int dp_a = x[a] + y[a]; int dp_b = x[b] + y[b]; int dn_a = x[a] - y[a]; int dn_b = x[b] - y[b]; if(dp_a != dp_b && dn_a != dn_b) return Inf; int d = abs(x[a] - x[b]); if(dp_a == dp_b){ if((dir[a] == 0 && dir[b] == 3) || (dir[a] == 1 && dir[b] == 2)) return d; return Inf; } if((dir[a] == 0 && dir[b] == 1) || (dir[a] == 3 && dir[b] == 2)) return d; return Inf; } int dis[N]; struct Line { int spd = 1, sz; vector<pii> Stop, Move; vector<pii> ans, mn; vector<int> lz; void Apply(int id, int x){ // debug(x); ans[id] = min(ans[id], pii(mn[id].F + x, mn[id].S)); lz[id] = min(lz[id], x); } void Shift(int id){ if(lz[id] != 1){ Apply(id << 1, lz[id]); Apply(id << 1 | 1, lz[id]); } lz[id] = 1; } void Build(int id, int L, int R){ lz[id] = 1; if(L + 1 == R){ ans[id] = {Inf, Stop[L].S}; mn[id] = Stop[L]; return ; } int mid = (L + R) >> 1; Build(id << 1, L, mid); Build(id<<1|1, mid, R); ans[id]=min(ans[id << 1], ans[id << 1 | 1]); mn[id] = min(mn[id << 1], mn[id << 1 | 1]); } void Off(int id, int idx, int L, int R){ if(L + 1 == R){ mn[id].F = Inf + Inf; ans[id] = mn[id]; return ; } int mid = (L + R) >> 1; Shift(id); if(idx < mid) Off(id << 1, idx, L, mid); else Off(id<<1|1, idx, mid, R); ans[id] = min(ans[id << 1], ans[id << 1 | 1]); mn[id] = min(mn[id << 1], mn[id << 1 | 1]); } void Add(int id, int l, int r, int x, int L, int R){ // for(int i = l; i < r; i++) // return ; if(r <= L || R <= l) return ; if(l <= L && R <= r){ Apply(id, x); return ; } int mid = (L + R) >> 1; Shift(id); Add(id << 1, l, r, x, L, mid); Add(id<<1|1, l, r, x, mid, R); ans[id] = min(ans[id << 1], ans[id << 1 | 1]); mn[id] = min(mn[id << 1], mn[id << 1 | 1]); } void Add_Stop(int pos, int id){ Stop.pb({pos, id}); } void Add_Move(int pos, int id){ Move.pb({pos, id}); } void Init(){ sz = Stop.size(); if(Stop.empty()) return ; for(auto &el : Stop) el.F /= spd; for(auto &el : Move) el.F /= spd; sort(all(Stop)); ans.resize(sz * 4); mn.resize(sz * 4); lz.resize(sz * 4); Build(1, 0, sz); } void Infect_Move(int pos, int id, int tm){ // debug(id); // debug(tm); pos /= spd; // int dbg = 0; // if(dbg){ // for(auto el : Stop){ // int i = el.S; // // cerr << "&& " << id << ' ' << i << '\n'; // if(el.F < pos + tm) continue; // if(mk[i]) continue; // int ds = Collision(id, i); // assert(ds == el.F - pos); // if(dis[i] > ds){ // st.erase({dis[i], i}); // dis[i] = ds; // st.insert({ds, i}); // } // } // } // for(auto [_pos, _id] : Stop){ // if(mk[_id]) continue; // if(pos + tm <= _pos && !mk[_id]){ // assert(Collision(id, _id) == _pos - pos); // if(dis[_id] > _pos - pos){ // st.erase({dis[_id], _id}); // dis[_id] = _pos - pos; // st.insert({dis[_id], _id}); // } // } // } int idx = lower_bound(all(Stop), pii(pos + tm, -1)) - Stop.begin(); if(idx == sz) return ; // debug(pos); Add(1, idx, sz, -pos, 0, sz); if(dis[ans[1].S] > ans[1].F){ st.erase({dis[ans[1].S], ans[1].S}); dis[ans[1].S] = ans[1].F; st.insert(ans[1]); } } void Infect_Stop(int pos, int id, int tm){ pos /= spd; int idx = lower_bound(all(Stop), pii(pos, id)) - Stop.begin(); // assert(idx < sz); assert(Stop[idx] == pii(pos, id)); Off(1, idx, 0, sz); if(dis[ans[1].S] > ans[1].F){ st.erase({dis[ans[1].S], ans[1].S}); dis[ans[1].S] = ans[1].F; st.insert(ans[1]); } } void Reset(){ Stop.clear(); Move.clear(); } }; Line DIA[4][4][N], U[N], R[N]; int CP[N], CN[N], CXX[N], CYY[N]; int rv[4][4], ty[4][4]; void Infect(int u, int tm){ assert(mk[u] == 0); mk[u] = 1; // for(int i = 0; i < n; i++){ // if(mk[i]) continue; // int ds = Collision(u, i); // if(ds != Inf) // vis.insert({u, i}); // if(ds >= tm && ds != Inf && dis[i] > ds){ // st.erase({dis[i], i}); // dis[i] = ds; // st.insert({ds, i}); // } // } // return ; // debug(u); int MAX = 1'000'000'000; int pos; for(int d2 = 0; d2 < 4; d2 ++){ if((dir[u] + d2) % 2 == 0) continue; pos = rv[dir[u]][d2] ? MAX - x[u] : x[u]; DIA[dir[u]][d2][ ty[dir[u]][d2] ? CN[u] : CP[u]].Infect_Move(pos, u, tm); pos = rv[d2][dir[u]] ? MAX - x[u] : x[u]; DIA[d2][dir[u]][ ty[d2][dir[u]] ? CN[u] : CP[u]].Infect_Stop(pos, u, tm); } int imp = dir[u] & 1 ? y[u] : x[u]; pos = rv[dir[u]][dir[u] ^ 2] ? MAX - imp : imp; DIA[dir[u]][dir[u] ^ 2][dir[u] & 1 ? CXX[u] : CYY[u]].Infect_Move(pos, u, tm); pos = rv[dir[u] ^ 2][dir[u]] ? MAX - imp : imp; DIA[dir[u] ^ 2][dir[u]][dir[u] & 1 ? CXX[u] : CYY[u]].Infect_Stop(pos, u, tm); } int Solve(){ dir[0] = 0; for(int i = 1; i < n; i++){ int X = abs(x[i] - x[0]); int Y = abs(y[i] - y[0]); if(X == Y){ if(x[i] < x[0]) dir[i] = 0; else dir[i] = y[i] < y[0] ? 3 : 1; } else { if(X > Y){ if( x[i] < x[0]) dir[i] = 0; else dir[i] = 2; } else { if( y[i] < y[0]) dir[i] = 3; else dir[i] = 1; } } } // cerr << "!! " ; // for(int i = 0; i < n; i++){ // cerr << dir[i] << ' '; // } // cerr << '\n'; // cerr << "!! " << x[0] << ' ' << y[0] << ' ' << x[1] << ' ' << y[1] << '\n'; // for(int i = 0; i < N; i++) R[i].Reset(), U[i].Reset(); for(int i = 0; i < 16; i++) for(int j = 0; j < N; j++) DIA[i >> 2][i & 3][j].Reset(); for(int i = 0; i < 4; i++) for(int j = 0; j < N; j++) DIA[i][i ^ 2][j].spd = 2; int MAX = 1'000'000'000; for(int i = 0; i < n; i++){ int pos; for(int d2 = 0; d2 < 4; d2 ++){ if((dir[i] + d2) % 2 == 0) continue; pos = rv[dir[i]][d2] ? MAX - x[i] : x[i]; DIA[dir[i]][d2][ ty[dir[i]][d2] ? CN[i] : CP[i]].Add_Move(pos, i); pos = rv[d2][dir[i]] ? MAX - x[i] : x[i]; DIA[d2][dir[i]][ ty[d2][dir[i]] ? CN[i] : CP[i]].Add_Stop(pos, i); } int imp = dir[i] & 1 ? y[i] : x[i]; pos = rv[dir[i]][dir[i] ^ 2] ? MAX - imp : imp; DIA[dir[i]][dir[i] ^ 2][dir[i] & 1 ? CXX[i] : CYY[i]].Add_Move(pos, i); pos = rv[dir[i] ^ 2][dir[i]] ? MAX - imp : imp; DIA[dir[i] ^ 2][dir[i]][dir[i] & 1 ? CXX[i] : CYY[i]].Add_Stop(pos, i); } for(int i = 0; i < 16; i++) for(int j = 0; j < N; j++) DIA[i >> 2][i & 3][j].Init(); memset(mk, 0, sizeof mk); fill(dis, dis + N, Inf); dis[0] = 0; st.insert({0, 0}); while(!st.empty()){ // cerr << "&&&&&&&\n"; // for(auto [a1, a2] : st) // cerr << a1 << ' ' << a2 << '\n'; // cerr << "-------\n"; int fr = st.begin() -> S; int tm = st.begin() -> F; st.erase(st.begin()); // if(tm > Inf) continue; // cerr << "!! " << fr << ' ' << tm << '\n'; Infect(fr, tm); } int res = 0; for(int i = 0; i < n; i++) res += mk[i]; return res; } int32_t main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); rv[3][0] = 1; rv[1][0] = 1; rv[2][1] = 1; rv[2][3] = 1; rv[2][0] = 1; rv[1][3] = 1; ty[0][1] = ty[1][0] = ty[2][3] = ty[3][2] = 1; cin >> n; vector<int> cp, cn, cxx, cyy; for(int i = 0; i < n; i++){ cin >> x[i] >> y[i]; cp.pb(x[i] + y[i]); cn.pb(x[i] - y[i]); cxx.pb(x[i]); cyy.pb(y[i]); } sort(all(cp)); sort(all(cn)); sort(all(cxx)); sort(all(cyy)); for(int i = 0; i < n; i++) CP[i] = lower_bound(all(cp), x[i] + y[i]) - cp.begin(); for(int i = 0; i < n; i++) CN[i] = lower_bound(all(cn), x[i] - y[i]) - cn.begin(); for(int i = 0; i < n; i++) CXX[i] = lower_bound(all(cxx), x[i]) - cxx.begin(); for(int i = 0; i < n; i++) CYY[i] = lower_bound(all(cyy), y[i]) - cyy.begin(); for(int i = 0; i < n; i++){ x[i] += x[i]; y[i] += y[i]; } int ans = 0; int MAX = 1'000'000'000; for(int _ = 0; _ < 4; _++){ ans = max(ans, Solve()); for(int i = 0; i < n; i++){ int _x = x[i]; x[i] = MAX-y[i]; y[i] = _x; } for(int i = 0; i < n; i++) swap(CP[i], CN[i]); for(int i = 0; i < n; i++) swap(CXX[i], CYY[i]); // break; } cout << ans << '\n'; // for(auto [a1, a2] : vis) // cerr << "! " << a1 << ' ' << a2 << '\n'; return 0; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...