希尔伯特曲线如图所示
观察易得为分形
暴力分形过程很容易,但是时间爆炸
逆向思考,对于任意点,可以递归求得分型过程
(设 左上角为第1进入块 左下2块 右下3块 右上4块)
且左上为原图形左旋, 下边两个都是原图形, 右上是原图形关于x = y对称
将以上分形过程做唯一映射并排序输出即可
有点卡常, vector string超时, 用5进制映射比较好
/*
Zeolim - An AC a day keeps the bug away
*/
//#pragma GCC optimize(2)
//#pragma GCC ("-W1,--stack=128000000")
#include <bits/stdc++.h>
using namespace std;
#define mp(x, y) make_pair(x, y)
#define fr(x, y, z) for(int x = y; x < z; ++x)
#define pb(x) push_back(x)
typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef std::pair <int, int> pii;
typedef std::vector <int> vi;
//typedef __int128 ill;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 386910137;
const ull P = 13331;
const int MAXN = 1e6 + 10;
struct node
{
ll x, y;
ll step;
}arr[MAXN];
ll t, now, lst;
void gao(ll x, ll y, ll w)
{
if(w == 1)
{
if(x == 1 && y == 1) lst = lst * 5 + 1;
if(x == 2 && y == 1) lst = lst * 5 + 2;
if(x == 2 && y == 2) lst = lst * 5 + 3;
if(x == 1 && y == 2) lst = lst * 5 + 4;
return ;
}
if(x <= w / 2 && y <= w / 2)
lst = lst * 5 + 1, gao(y, x, w / 2);
else if(x > (w / 2) && y <= (w / 2))
lst = lst * 5 + 2, gao(x - (w / 2), y, w / 2);
else if( x <= (w / 2) && y > (w / 2))
lst = lst * 5 + 4, gao(w - y + 1, (w / 2) - x + 1, w / 2);
else
lst = lst * 5 + 3, gao(x - (w / 2), y - (w / 2), w / 2);
}
bool cmp(node a, node b)
{
return a.step < b.step;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
//freopen("d:out.txt","w",stdout);
//freopen("d:in.txt","r",stdin);
int n, t;
cin >> n >> t;
for(int i = 0; i < n; ++i)
{
cin >> arr[i].x >> arr[i].y;
now = i, lst = 1;
gao(arr[i].x, arr[i].y, 1ll << t);
arr[i].step = lst;
}
sort(arr, arr + n, cmp);
fr(i, 0, n)
cout << arr[i].x << ' ' << arr[i].y << '
';
return 0;
}