[题解] 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 (n \le 4\times 10^4)\) 个点编码成一个长度不超过 \(3n\) 的值域为 \([0,2 \times 10 ^ 9]\) 的整型数组,数组被打乱后传入 decode,返回一个长度 \(2n\) 的数组,为原来的点的坐标,形如 \(x_i,y_i,x_j,y_j,\cdots,x_k,y_k\),不要求点的顺序与原来一致 。
\(n \le 4 \times 10^4,0 \le x,y \le 5 \times 10^8\)
解法
首先长度 \(3n\),根据我几乎没有的信息熵 知识 直觉猜测其中 \(\mathcal{O}(n)\) 是给 \(x\) 的,\(\mathcal{O}(n)\) 是给 \(y\) 的,剩下大约 \(n\) 是给一个索引的。
然后因为会被打乱,需要保证生成的序列是一个递增的形式,这样直接排序就能恢复原来的序列。
那么就首先把所有节点按照 \(x,y\) 双关键字排序,把 \(x_i\) 原样加入编码数组,占用长度 \(n\)。
把 \(y\) 排序后去重,把 \(y_i + 5 \times 10^8\) 加入编码数组,保证排在 \(x\) 之后。
最后把 \(x_i\) 对应的 \(y\) 离散化后的值加上 \(10^9 + 2\) 加入编码数组,但是这时候我们发现不能保证位置是递增的,于是我们改为加入前缀和,解码时差分即可。
值域大概是一个 \(1.8 \times 10^9\),随便过。
代码
#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;
}
作者:AstatineAi
本文为 作者 AstatineAi 的原创,遵循CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接及本声明。

浙公网安备 33010602011771号