题目链接:https://codeforces.com/contest/1270/problem/E
题意:给定n个点,现在需要将这n个点划分为2个集合,将集合内任意两点的欧几里得距离标记为红,将集合间的点对的欧几里得距离标记为绿,现要求红色和绿色距离不能有相同的,求划分方案,有多个划分方案,输出任意一种。保证至少有一种划分方案。
官方题解:奇数偶划分,划分为00、01、10、11;如果还分不出时,继续除2划分。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1010;
int n;
int x[maxn],y[maxn];
vector<int> v[5];//00 01 10 11
vector<int> v2[5];// 0 1
int Judge(int x,int y){
return (((x%2)<<1)+(y%2));
}
int Judge2(int x,int y){
return (x+y)%2;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&y[i]);
x[i]+=1000000;
y[i]+=1000000;
}
while(1){
for(int i=0;i<4;i++) v[i].clear();
v2[0].clear();v2[1].clear();
for(int i=1;i<=n;i++){
v[Judge(x[i],y[i])].push_back(i);
v2[Judge2(x[i],y[i])].push_back(i);
}
if(!v2[0].empty()&&!v2[1].empty()){
int m=(int)v2[0].size();
printf("%d\n",m);
for(int j=0;j<m;j++) printf("%d ",v2[0][j]);
break;//
}else if(!v[0].empty()&&!v[3].empty()){
int m=(int)v[0].size();
printf("%d\n",m);
for(int j=0;j<m;j++) printf("%d ",v[0][j]);
break;//
}else if(!v[1].empty()&&!v[2].empty()){
int m=(int)v[1].size();
printf("%d\n",m);
for(int j=0;j<m;j++) printf("%d ",v[1][j]);
break;//
}else{
for(int i=1;i<=n;i++) x[i]>>=1,y[i]>>=1;
}
}
return 0;
}