[题解] APIO 2022 Practice T3 Treasure

前言#

摆烂了,正好在 APIO 试机练习赛看到这道挺水但是挺有意思的题,做完写个题解。

题意#

通信题,实现两个函数:

std::vector<int> encode(std::vector<int> x,std::vector<int> y)
std::vector<int> decode(std::vector<int> e)

其中 encode 实现把给出的 n(n4×104) 个点编码成一个长度不超过 3n 的值域为 [0,2×109] 的整型数组,数组被打乱后传入 decode,返回一个长度 2n 的数组,为原来的点的坐标,形如 xi,yi,xj,yj,,xk,yk,不要求点的顺序与原来一致 。

n4×104,0x,y5×108

解法#

首先长度 3n,根据我几乎没有的信息熵 知识 直觉猜测其中 O(n) 是给 x 的,O(n) 是给 y 的,剩下大约 n 是给一个索引的。

然后因为会被打乱,需要保证生成的序列是一个递增的形式,这样直接排序就能恢复原来的序列。

那么就首先把所有节点按照 x,y 双关键字排序,把 xi 原样加入编码数组,占用长度 n

y 排序后去重,把 yi+5×108 加入编码数组,保证排在 x 之后。

最后把 xi 对应的 y 离散化后的值加上 109+2 加入编码数组,但是这时候我们发现不能保证位置是递增的,于是我们改为加入前缀和,解码时差分即可。

值域大概是一个 1.8×109,随便过。

代码#

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include "treasure.h"

#define rep(a,b,c) for(int a = (b);a <= (c);++a)
#define repb(a,b,c) for(int a = (b);a >= (c);--a)
#define repl(a,b,c) for(int a = (b);a < (c);++a)
#define repr(a,b,c) for(int  a = (b);a > (c);--a)
#define repg(a,b) for(int a = head[b];~a;a = e[a].nxt)
#define mems(a,b) memset(a,b,sizeof(a))
#define O(x) std::cerr << #x << ':' << x << std::endl;

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = __uint128_t;
using f32 = float;
using f64 = double;
using f80 = long double;
using pii = std::pair<int,int>;

constexpr int N = 40000;
constexpr int C = 500000001;
constexpr int D = 1000000002;

std::vector<int> encode(std::vector<int> x,std::vector<int> y) {
	std::vector<pii> pt;
	std::vector<int> r,d;
	repl(i,0,(int)x.size()) pt.emplace_back(x[i],y[i]);
	std::sort(pt.begin(),pt.end());
	std::sort(x.begin(),x.end());
	std::sort(y.begin(),y.end());
	y.erase(std::unique(y.begin(),y.end()),y.end());
	repl(i,0,(int)x.size()) r.emplace_back(x[i]);
	repl(i,0,(int)y.size()) r.emplace_back(y[i] + C);
	for(auto p : pt) {
		int py = std::lower_bound(y.begin(),y.end(),p.second) - y.begin();
		d.emplace_back(py);
	}
	int sum = 0;
	for(auto dis : d) {
		sum += dis;
		r.emplace_back(sum + D);
	}
	return r;
}

std::vector<int> decode(std::vector<int> e) {
	std::sort(e.begin(),e.end());
	std::vector<int> px,py,pd,r;
	int n = 0;
	while(e[n] <= 5e8)
		px.emplace_back(e[n++]);
	int ny = n;
	while(e[ny] <= 1e9 + 1)
		py.emplace_back(e[ny++]);
	pd.emplace_back(e[ny] - D);
	repl(i,1,n)
		pd.emplace_back(e[ny + i] - e[ny + i - 1]);
	repl(i,0,n) {
		int x = px[i];
		int y = py[pd[i]];
		r.emplace_back(x);
		r.emplace_back(y - C);
	}
	return r;
}
posted @   AstatineAi  阅读(143)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示
主题色彩