我们把所有点分成四类
$A_{0,0},A_{0,1},A_{1,0},A_{1,1}$
发现如果$A_{0,0}+A_{1,1} > 0$并且$A_{0,1}+A_{1,0} > 0$或者$A_{0,0}+A_{0,1} > 0$并且$A_{1,0} + A_{1,1} > 0$,这样可以直接得出答案
剩下的情况就是四种只存在一种的情况,这种情况把所有坐标缩小一倍,相等关系不变。
于是复杂度$O(nlog(n^2))$
这个想法根本没想到 感觉很奇妙 不过似乎有一种2-sat解法 可惜比赛的时候2-sat忘光了
在宿舍里打比赛果然手速减半 又掉分了
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; int n; int x[maxn], y[maxn], cnt[2][2]; int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d%d", &x[i], &y[i]); } while(1) { int s = 0; memset(cnt, 0, sizeof(cnt)); for(int i = 1; i <= n; ++i) { ++cnt[x[i] & 1][y[i] & 1]; } vector<int> ans; if(cnt[0][0] + cnt[1][1] > 0 && cnt[0][1] + cnt[1][0] > 0) { for(int i = 1; i <= n; ++i) { if(x[i] + y[i] & 1) { ans.push_back(i); } } printf("%d ", ans.size()); for(auto x : ans) { printf("%d ", x); } return 0; } if(cnt[0][0] + cnt[0][1] > 0 && cnt[1][0] + cnt[1][1] > 0) { for(int i = 1; i <= n; ++i) { if(x[i] & 1) { ans.push_back(i); } } printf("%d ", ans.size()); for(auto x : ans) { printf("%d ", x); } return 0; } for(int i = 1; i <= n; ++i) { x[i] >>= 1; y[i] >>= 1; } } return 0; }