Codeforces Good Bye 2019 E. Divide Points

题意:
给出n个点,将这些点分成两个集合,使得没有任何属于同集合的两点的欧几里得距离等于不同集合两点的欧几里得距离,集合非空,输出任意一个集合的个数和该集合所有点的下标


题解:
偷偷用cf的题解水一篇题解应该没人发现吧(

我们将点按x,y的奇偶分成4组, A 00 A_{00} A00表示x,y均为偶数… A 01 , A 10 , A 11 A_{01},A_{10},A_{11} A01,A10,A11同理。

首先如果所有点都属于同一组中,那么我们把它所有的坐标除以2(如果是坐标是奇数,需要先减1)以后,只是图像缩小了2倍,所有点之间的距离缩小了2倍,但是相对距离都是没有变的,所以对于新点的有效分区对于旧点依然有效

再看如果至少有两组的点存在:

如果至少有一个点的坐标和为奇数,且至少有一个点的坐标和为偶数,那么我们可以直接按坐标和的奇偶分区,因为坐标和为偶数的点,和它同一集合的点之间的距离一定是偶数,而它们到坐标为奇数的点的距离一定是奇数,所以这样分区也是合理的。

现在还剩下一种的情况就是所有点的坐标和都为奇数/偶数,也就是说现在的点形成的要么是0 0和1 1,要么是1 0和0 1这样的点组,现在我们以0 0和1 1为例,我们将这两组直接分开,那么0 0的点组之间的距离一定是%4等于0的,而0 0到1 1之间的距离一定是%4等于2的,所以这样分区也是合理的,那么另一种情况同理也可以推出是一样的。


AC代码:

#pragma GCC optimize(2)
#include
#include
using namespace std;
using namespace __gnu_cxx;
#define LL long long
#define pii pair
#define mp(a,b) make_pair(a,b)
const int MAXN = 1e3+10;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
pii v[MAXN]; vector<int> res;
int cnt[2][2];
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    int n; scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d%d",&v[i].first,&v[i].second);
    for(int i=0;i<n;i++) v[i].first+=1e6,v[i].second+=1e6;
    while(true){
        memset(cnt,0,sizeof(cnt));
        for(int i=0;i<n;i++) cnt[v[i].first%2][v[i].second%2]++;
        if(cnt[0][0]+cnt[1][1]>0 && cnt[0][1]+cnt[1][0]>0){
            for(int i=0;i<n;i++) if(v[i].first%2==v[i].second%2) res.push_back(i+1);
            printf("%d\n",res.size());
            for(int i=0;i<res.size();i++) printf("%d ",res[i]);
            return 0;
        }
        if(cnt[0][0]+cnt[0][1]>0 && cnt[1][0]+cnt[1][1]>0){
            for(int i=0;i<n;i++) if(v[i].first%2==0) res.push_back(i+1);
            printf("%d\n",res.size());
            for(int i=0;i<res.size();i++) printf("%d ",res[i]);
            return 0;
        }
        int x=0,y=0;
        for(int i=0;i<2;i++) for(int j=0;j<2;j++) if(cnt[i][j]) x=i,y=j;
        for(int i=0;i<n;i++) v[i].first=(v[i].first-x)/2,v[i].second=(v[i].second-y)/2;
    }
    return 0;
}

你可能感兴趣的:(思维题)