This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// Knapsack DP is harder than FFT.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll;
#define ff first
#define ss second
#define pb emplace_back
#define AI(x) begin(x),end(x)
template<class I>bool chmax(I&a,I b){return a<b?(a=b,true):false;}
template<class I>bool chmin(I&a,I b){return b<a?(a=b,true):false;}
#ifdef OWO
#define debug(args...) SDF(#args, args)
#define OIU(args...) ostream& operator<<(ostream&O,args)
#define LKJ(S,B,E,F) template<class...T>OIU(S<T...>s){O<<B;int c=0;for(auto i:s)O<<(c++?", ":"")<<F;return O<<E;}
LKJ(vector,'[',']',i)LKJ(deque,'[',']',i)LKJ(set,'{','}',i)LKJ(multiset,'{','}',i)LKJ(unordered_set,'{','}',i)LKJ(map,'{','}',i.ff<<':'<<i.ss)LKJ(unordered_map,'{','}',i.ff<<':'<<i.ss)
template<class...T>void SDF(const char* s,T...a){int c=sizeof...(T);if(!c){cerr<<"\033[1;32mvoid\033[0m\n";return;}(cerr<<"\033[1;32m("<<s<<") = (",...,(cerr<<a<<(--c?", ":")\033[0m\n")));}
template<class T,size_t N>OIU(array<T,N>a){return O<<vector<T>(AI(a));}template<class...T>OIU(pair<T...>p){return O<<'('<<p.ff<<','<<p.ss<<')';}template<class...T>OIU(tuple<T...>t){return O<<'(',apply([&O](T...s){int c=0;(...,(O<<(c++?", ":"")<<s));},t),O<<')';}
#else
#pragma GCC optimize("Ofast")
#define debug(...) ((void)0)
#endif
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
namespace Map {
// from https://gist.github.com/Chillee/3bd6ee4429abb4a2e7c19959fb1490ae#file-hash-table-cpp
struct chash {
const int RANDOM = (long long)(make_unique<char>().get()) ^ chrono::high_resolution_clock::now().time_since_epoch().count();
static unsigned long long hash_f(pii p) {
unsigned long long x = p.first * 1000696969LL + p.second;
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
unsigned long long operator()(pii x) const { return hash_f(x) ^ RANDOM; }
};
typedef gp_hash_table<pii, int, chash> gp;
}
const int kN = 150051;
const int kB = kN * 9;
int n, t;
pii pos[kB];
Map::gp ids;
int tot = 0;
int skyToBlock[kN];
int blockToSky[kB];
bool built[kB];
int component[kB];
vector<int> inComponent[kB];
vector<int> G4[kB], G8[kB];
int infinity;
void newBlock(int r, int c) {
pii p(r, c);
auto it = ids.find(p);
if (it != end(ids)) return;
ids[p] = ++tot;
pos[tot] = p;
component[tot] = tot;
inComponent[tot].pb(tot);
}
bool isAP(int i) {
debug(i, pos[i]);
static bool has[3][3];
static int com[3][3];
static int cu, cd, cl, cr, ci;
for (int &j: G8[i]) {
int x = pos[j].ff - pos[i].ff + 1;
int y = pos[j].ss - pos[i].ss + 1;
has[x][y] = built[j];
com[x][y] = component[j];
}
cu = com[0][1]; cd = com[2][1];
cl = com[1][0]; cr = com[1][2];
// debug(cu, cd, cl, cr);
// debug(has[0][0], has[0][1], has[0][2]);
// debug(has[1][0], has[1][1], has[1][2]);
// debug(has[2][0], has[2][1], has[2][2]);
if (!has[0][1] and !has[1][2] and cu == cr and has[0][2] and
(has[0][0] or has[1][0] or has[2][0] or has[2][1] or has[2][2]))
return true;
if (!has[0][1] and !has[1][0] and cu == cl and has[0][0] and
(has[0][2] or has[1][2] or has[2][0] or has[2][1] or has[2][2]))
return true;
if (!has[2][1] and !has[1][2] and cd == cr and has[2][2] and
(has[0][0] or has[1][0] or has[2][0] or has[0][1] or has[0][2]))
return true;
if (!has[2][1] and !has[1][0] and cd == cl and has[2][0] and
(has[0][2] or has[1][2] or has[2][2] or has[0][0] or has[0][1]))
return true;
if (!has[0][1] and !has[2][1] and cu == cd and
(has[0][0] or has[1][0] or has[2][0]) and
(has[0][2] or has[1][2] or has[2][2]))
return true;
if (!has[1][0] and !has[1][2] and cl == cr and
(has[0][0] or has[0][1] or has[0][2]) and
(has[2][0] or has[2][1] or has[2][2]))
return true;
ci = component[infinity];
if (cu == ci or cd == ci or cl == ci or cr == ci)
return false;
return true;
}
bool canErase[kB];
set<int, greater<int>> choose;
void updateSky(int i) {
bool ap = isAP(skyToBlock[i]);
if (ap and canErase[i])
choose.erase(i);
if (!ap and !canErase[i])
choose.insert(i);
canErase[i] = !ap;
}
// tissue is just a random name for timestamp
int lastUpdate[kB], tissue;
void merge(int i, int j, bool u) {
if (i == j) return;
if (inComponent[i].size() < inComponent[j].size())
swap(i, j);
for (int &v: inComponent[j]) {
component[v] = i;
inComponent[i].pb(v);
}
if (u) {
++tissue;
for (int &v: inComponent[j])
for (int &w: G8[v])
if (built[w] and lastUpdate[w] < tissue) {
debug(w, built[w], pos[w], skyToBlock[w]);
lastUpdate[w] = tissue;
updateSky(blockToSky[w]);
}
}
inComponent[j].clear();
}
void remove(int i) {
built[i] = false;
for (int &j: G4[i]) if (!built[j])
merge(component[i], component[j], true);
}
bool vis[kB];
void dfs(int u, int &reach) {
++reach; vis[u] = true;
for (int &v: G8[u])
if (built[v] and !vis[v])
dfs(v, reach);
}
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n >> t;
pii minPos(1e9 + 7, 1e9 + 7);
for (int r, c, i = 1; i <= n; ++i) {
cin >> r >> c;
for (int dx = -1; dx <= 1; ++dx)
for (int dy = -1; dy <= 1; ++dy)
newBlock(r + dx, c + dy);
int id = ids[pii(r, c)];
skyToBlock[i] = id;
blockToSky[id] = i;
built[id] = true;
minPos = min(minPos, pii(r, c));
}
--minPos.ff;
infinity = ids[minPos];
debug("Done 1");
for (int i = 1; i <= tot; ++i) {
auto &[r, c] = pos[i];
for (int dx = -1; dx <= 1; ++dx)
for (int dy = -1; dy <= 1; ++dy) {
if (dx == 0 and dy == 0) continue;
pii np(r + dx, c + dy);
auto it = ids.find(np);
if (it == end(ids)) continue;
int j = ids[np];
G8[i].pb(j);
if (dx == 0 or dy == 0) {
G4[i].pb(j);
if (!built[i] and !built[j])
merge(component[i], component[j], false);
}
}
}
//for (int i = 1; i <= n; ++i)
// debug(i, skyToBlock[i], pos[skyToBlock[i]]);
//for (int i = 1; i <= tot; ++i)
// debug(i, pos[i], built[i], G4[i], G8[i]);
debug("Done 2");
int reach = 0;
dfs(skyToBlock[1], reach);
if (reach != n) {
cout << "NO\n";
return 0;
}
debug("Done 3");
for (int i = 1; i <= n; ++i)
updateSky(i);
cout << "YES\n";
vector<int> ans;
for (int i = 1; i <= n; ++i) {
//debug(choose);
int u = *begin(choose);
choose.erase(u);
ans.pb(u);
remove(skyToBlock[u]);
}
reverse(AI(ans));
for (int &u: ans)
cout << u << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |