[题解] 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
实现把给出的 个点编码成一个长度不超过 的值域为 的整型数组,数组被打乱后传入 decode
,返回一个长度 的数组,为原来的点的坐标,形如 ,不要求点的顺序与原来一致 。
解法#
首先长度 ,根据我几乎没有的信息熵 知识 直觉猜测其中 是给 的, 是给 的,剩下大约 是给一个索引的。
然后因为会被打乱,需要保证生成的序列是一个递增的形式,这样直接排序就能恢复原来的序列。
那么就首先把所有节点按照 双关键字排序,把 原样加入编码数组,占用长度 。
把 排序后去重,把 加入编码数组,保证排在 之后。
最后把 对应的 离散化后的值加上 加入编码数组,但是这时候我们发现不能保证位置是递增的,于是我们改为加入前缀和,解码时差分即可。
值域大概是一个 ,随便过。
代码#
#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
出处:https://www.cnblogs.com/AstatineAi/p/APIO-practise-C.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本