• CodeForces Goodbye2019 E.Divide Points (构造)


    题目:传送门

    思路及代码参考了这位大佬的博客 点此跳转

    现将点分为四类 :(0表示偶数,1表示奇数)

    1. (0,0)
    2. (1,1)
    3. (0,1)
    4. (1,0)

    如果有至少一个点属于 3或4 ,则可以将所有点分为 {1,2} 和 {3,4};
    这样划分,集合内部距离平方为偶,集合之间的距离平方为奇数,满足题意;

    如果没有点属于 3或4 ,则将所有点分为 {1} 和 {2} ;
    这样划分 1:( 2 * x,2 * y ) ; 2: ( 2 * z + 1,2 * k + 1 ) ;
    那么集合内部是 x1-x2 与 y1-y2 都是偶数
    集合之间 则都是奇数;
    平方和相加,集合内部的距离 为两个偶数之和
    平方和相加,集合之间的距离 为 两个奇数之和(奇数的平方还是奇数)
    故满足题意;

    如果所有点都是第一类的,那么我对所有坐标除以2,这样操作是对距离的相对关系是没有任何影响的,知道出现了非第一类点,就可以开始分类了(不存在奇数除以2的情况);

    因为我们是围绕第一类进行构造,为了保证一定会有第一类点,我们将所有坐标的进行平移,代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int N=1e6+5;
    const int inf=0x3f3f3f3f;
    const LL INF=1LL<<50;
    #define ls (i<<1)
    #define rs (i<<1|1)
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define debug puts("...")
    LL read()
    {
        LL x=0,t=1;
        char ch=getchar();
        while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
        while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
        return x*t;
    }
    int x[N],y[N];
    vector<int> a,b;
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
            x[i]=read(),y[i]=read();
        for(int i=n;i;i--) x[i]-=x[1],y[i]-=y[1]; ///保证一定有(偶,偶)这一种情况
        while(1)
        {
            for(int i=1;i<=n;i++)
                if(x[i]%2||y[i]%2) goto out;
            for(int i=1;i<=n;i++)
                x[i]>>=1,y[i]>>=1;
        }out:;
        for(int i=1;i<=n;i++)
        {
            //printf("x=%d , y=%d
    ",x[i],y[i]);
            if(x[i]%2&&y[i]%2) b.pb(i);
            else if(x[i]%2==0&&y[i]%2==0) a.pb(i);
        }
        if(a.size()+b.size()==n)
        {
            printf("%d
    ",a.size());
            for(int i=0;i<a.size();i++)
                printf("%d ",a[i]);
        }
        else
        {
            printf("%d
    ",a.size()+b.size());
            for(int i=0;i<a.size();i++)
                printf("%d ",a[i]);
            for(int i=0;i<b.size();i++)
                printf("%d ",b[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    RWCString 定义 memeroy leak
    打开eclipse报错
    Eclipse 增加php插件
    Shell 字符串的截取
    【转载】Shell判断字符串包含关系的几种方法
    Shell $? $* $@ 等含义
    Shell 获取指定行的内容
    概念性进程
    网络编程
    模块详解
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12215030.html
Copyright © 2020-2023  润新知