#include #include #include #include #include #include #include #include #include #include #include #include typedef long long llong; const int MAXN = 100000 + 10; const int MAXN2 = 5000 + 10; const llong INF = 4e18; const int INTINF = 2e9; int n; llong r; struct Point { llong x, y; int idx; friend bool operator < (const Point &a, const Point &b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } }; Point p[MAXN]; bool good(int a, int b) { return (p[a].x - p[b].x) * (p[a].x - p[b].x) + (p[a].y - p[b].y) * (p[a].y - p[b].y) >= 4 * r * r; } int dp2[MAXN]; std::vector solution; std::unordered_map bucketMap; std::vector byBucket[MAXN]; std::vector goodPos[MAXN]; std::vector mySolution[MAXN]; bool goodWithNext[MAXN]; std::vector dpFast[MAXN]; int bucketValue[MAXN]; void getSolutionOf(int bucket) { int cntAdded = 0; int pos = dpFast[bucket].size() - 1; while (pos > 0) { if (dpFast[bucket][pos] == dpFast[bucket][goodPos[bucket][pos]] + 1) { cntAdded++; mySolution[bucket].push_back(byBucket[bucket][pos]); pos = goodPos[bucket][pos]; } else { pos--; } } assert(cntAdded == dpFast[bucket].back()); } void addSolutionOf(int bucket) { for (const int &u : mySolution[bucket]) { solution.push_back(p[u].idx); } } int firstAfter(int bucket, int x) { int ll = 0, rr = byBucket[bucket].size(), mid; while (ll < rr - 1) { mid = (ll + rr) / 2; if (p[byBucket[bucket][mid]].x <= x) ll = mid; else rr = mid; } return rr; } int firstBefore(int bucket, int x) { int ll = 0, rr = byBucket[bucket].size(), mid; while (ll < rr - 1) { mid = (ll + rr) / 2; if (p[byBucket[bucket][mid]].x < x) ll = mid; else rr = mid; } return ll; } bool findIfNotOverlapping(int bucketA, int bucketB) { for (const int &idx : mySolution[bucketA]) { int from = firstAfter(bucketB, p[idx].x - 2 * r); int to = firstBefore(bucketB, p[idx].x + 2 * r); for (const int &idx2 : mySolution[bucketB]) { if (!good(idx, idx2)) { return false; } } } return true; } int answer[MAXN2]; int dp[MAXN2][MAXN2]; int idx[MAXN2][MAXN2]; void getSolutionOf2(int bucket) { int middle = -1; int next = -1; // std::vector curr; for (int i = 1 ; i <= n ; ++i) { for (const int &u : curr) { if (!good(u, i)) { can = false; break; } } if (can) { curr.push_back(i); } } if (curr.size() > solution.size()) { solution.clear(); for (const int &idx : curr) { solution.push_back(p[idx].idx); } } std::shuffle(p + 1, p + 1 + n, rng); } while ((clock() - begTime) < 4.5 * CLOCKS_PER_SEC); } void fastButBad() { p[0].x = p[0].y = -INTINF; std::set vals; std::sort(p + 1, p + 1 + n); for (int i = 1 ; i <= n ; ++i) { vals.insert(p[i].y / (2 * r)); } int cnt = 0; for (const int &val : vals) { bucketMap[val] = ++cnt; bucketValue[cnt] = val; } for (int i = 1 ; i <= cnt ; ++i) { byBucket[i].push_back(0); } for (int i = 1 ; i <= n ; ++i) { byBucket[bucketMap[p[i].y / (2 * r)]].push_back(i); } for (int i = 1 ; i <= cnt ; ++i) { dpFast[i].resize(byBucket[i].size(), 0); goodPos[i].resize(byBucket[i].size(), 0); for (int j = 1 ; j < byBucket[i].size() ; ++j) { dpFast[i][j] = dpFast[i][j - 1]; goodPos[i][j] = firstAfter(i, p[byBucket[i][j]].x - 2 * r) - 1; dpFast[i][j] = std::max(dpFast[i][j], dpFast[i][goodPos[i][j]] + 1); } getSolutionOf(i); } for (int i = 1 ; i < cnt ; ++i) { if (bucketValue[i - 1] == bucketValue[i] - 1) { goodWithNext[i] = findIfNotOverlapping(i, i + 1); } } bucketValue[0] = -INTINF; for (int i = 1 ; i <= cnt ; ++i) { dp2[i] = dp2[i - 1]; if (bucketValue[i - 1] < bucketValue[i] - 1 || goodWithNext[i - 1]) dp2[i] = dp2[i - 1] + dpFast[i].back(); else dp2[i] = std::max(dp2[i], dp2[i - 2] + dpFast[i].back()); } int pos = cnt; while (pos > 0) { if (bucketValue[pos - 1] < bucketValue[pos] - 1 || goodWithNext[pos - 1]) { addSolutionOf(pos); pos--; } else if (dp2[pos] == dp2[pos - 1]) { pos--; } else { addSolutionOf(pos); pos -= 2; } } int sum = 0; for (int i = 1 ; i <= cnt ; ++i) { sum += answer[i]; } assert(solution.size() == dp2[cnt]); } void input() { std::cin >> n >> r; for (int i = 1 ; i <= n ; ++i) { std::cin >> p[i].x >> p[i].y; p[i].y--; p[i].idx = i; } } void print() { std::cout << solution.size() << '\n'; for (const int &idx : solution) { std::cout << idx << ' '; } std::cout << '\n'; } void fastIOI() { // freopen("mars.in", "r", stdin); // freopen("mars.out", "w", stdout); std::ios_base :: sync_with_stdio(0); std::cout.tie(nullptr); std::cin.tie(nullptr); } int main() { begTime = clock(); fastIOI(); input(); good(); // if (n <= 5000) good(); // else fastButBad(); print(); return 0; }