Codeforces Round #319 (Div. 2) E - Points on Plane, 第一次做“构造法”

题意:给出n个点,要求找出一个排列顺序使得一条经过所有点一次的路径长度<25*10^8 .(每两个点之间的长度是哈密顿距离:abs(x1-x2)+abs(y1-y2) );

首先我们三个人在比赛中都以为其实就是要我们找最短的路径,这是最sb的错误,这种问题显然不是要你找最短,只需要找到符合条件的路径就行。
因为n<10^6 , 每个点 0 < x,y<10^6
这题用了一个很巧妙地构造法
10^6
我们可以分成 10^3个 1-1000 的块
Codeforces Round #319 (Div. 2) E - Points on Plane, 第一次做“构造法”_第1张图片

我们可以分成 奇偶的方块
在奇数块里面 按y递增的顺序排列,在偶数里面按y递减的顺序排列;
这种情况下,在某一个块里面最差的情况:
y轴上的贡献度必然最大是1e6,x轴的贡献度最大应该是 n * 1000 (n就是这个块里面的点的个数), 所以所有点加起来最多也才1e9 + 1e9 的样子,必然是小于2.5*1e9的,所以就满足题目的条件了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define ll __int64
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
struct node{
    int x,y;
    int pos;
};
node f[1000005];
bool cmp(node a,node b){
    if(a.x/1000==b.x/1000){
         if(a.x/1000%2==0) return a.y<b.y;
         else return a.y>b.y;
    }
    else return a.x/1000<b.x/1000;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        f[i].pos=i;
        int x,y;
        scanf("%d %d",&x,&y);
        f[i].x=x;
        f[i].y=y;
    }
    sort(f+1,f+n+1,cmp);
    for(int i=1;i<=n;i++)
        printf("%d ",f[i].pos);
    printf("\n");
return 0;
}

你可能感兴趣的:(Codeforces Round #319 (Div. 2) E - Points on Plane, 第一次做“构造法”)