P10033 题解
不喜欢特判?不喜欢分讨?不喜欢被卡 corner?不喜欢证明?不喜欢动脑子?
那就看这篇题解!
感性思路
首先感性地感受一下题目宽泛的限制条件题解区各种花式的构造方法就不难想出,符合条件的序列实在很多,那不是随便构造?但是随便上随机化还是很容易被卡而且常数太大,又不想写屎山分讨被 corner 卡到心态爆炸,怎么办!
爆搜!直接每一位枚举 \([1, n]\),先不说枚举到一个合法解的复杂度,朴素地检查需要把序列每一位都搜完,并且光检查就要 \(O(n^2)\)。我们需要将序列合法条件进行转换,最好做到若一位填的不合法立刻剪枝,就有希望很对!
首先 \(\sum\limits_{i=l}^{r} a_i = \sum\limits_{i=l}^{r} p_i\) 容易转换成 \(\sum\limits_{i=l}^{r} (a_i - p_i) = 0\),令 \(b_i = a_i - p_i\),那么这个条件就再次转换为序列 \(b\) 的前缀和序列没有两项是相同的(注意也不能为 0)。那么搜索的时候再记一个参数表示当前 \(a_i-p_i\) 的前缀和即可。注意出题人卡了一个 \(n \log n\),于是要用 unordered_set 检查。
理性证明
刚才只是感性理解了一下时间和做法,实际上这个时间是可以被证明的!
首先不难发现每次检查的都是一个前缀,那么也就是说如果前 \(i\) 个数合法,第 \(i + 1\) 个数没有冲突,那么前 \(i + 1\) 个数合法。搜索产生回溯当且仅当第 \(i + 1\) 个数与任意一个前缀都冲突。而随着 \(n\) 增大,前缀和的产生的值域范围也是非常大的,也就是不满的。可以证明 \(n\) 大于一个定值是一定不会产生回溯的。只有经过特殊构造的 \(n\) 很小的时候才会产生回溯。但是还有一个问题,无解会将搜索跑满,那时间复杂度就不对了?但注意无解是强于存在回溯的,也就是值域要求更加窄。可以证明,当且仅当 \(n=2\) 时才会产生无解。
还有一个好玩的性质,只要有解,那么必定能构造出一组使得 \(\forall p_i \leq 4\)。综上所述,可以认为时间复杂度最坏为 \(O(Vn)\),其中 \(V\) 为构造一组合法的 \(p\) 要用到的最大的 \(p_i\),最大为常数 4。复杂度正确。
实现代码
#include <iostream>
#include <unordered_set>
using namespace std;
typedef long long ll;
int uread() {
char c = getchar();
while (c < '0' || c > '9') {
c = getchar();
}
int num = 0;
while (c >= '0' && c <= '9') {
num = (num << 1) + (num << 3) + (c ^ 48);
c = getchar();
}
return num;
}
const int N = 1e6 + 1;
int n;
int a[N], b[N];
unordered_set<ll> st;
bool dfs(int pos, ll sum) {
if (pos == n + 1) {
return true;
}
for (int i = 1; i <= n; ++i) {
if (a[pos] == i) {
continue;
}
ll now = sum + a[pos] - i;
if (st.count(now)) {
continue;
}
st.insert(now);
b[pos] = i;
if (dfs(pos + 1, now)) {
return true;
}
st.erase(now);
}
return false;
}
void solve() {
n = uread();
for (int i = 1; i <= n; ++i) {
a[i] = uread();
}
st.clear(); st.insert(0ll);
if (!dfs(1, 0ll)) {//或直接特判 n == 2
puts("-1");
return ;
}
for (int i = 1; i <= n; ++i) {
printf("%d ", b[i]);
}
putchar('\n');
}
int main(int argc, const char * argv[]) {
int T = uread();
while (T--) {
solve();
}
return 0;
}
P10033 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- 基于阿里云 Serverless 快速部署 function 的极致体验
1.Serverless 前世今生 1.1 Serverless 背景介绍 云计算的不断发展,涌现出很多改变传统IT架构和运维方式的新技术,而以虚拟机.容器.微服务为代表的技术更是在各个层面不断提升云 ...
- <vue初体验> 基础知识 3、vue的计数器
系列导航 <vue初体验> 一. vue的引入和使用体验 <vue初体验> 二. vue的列表展示 <vue初体验> 三. vue的计数器 <vue初体验&g ...
- C#商品金额大小写转换
见图 代码如下 public string NumToChinese(string x) { //数字转换为中文后的数组 string[] P_array_num = new string[] { & ...
- RSA 加密,解密,签名,验签
一.RSA加密简介 RSA加密是一种非对称加密.可以在不直接传递密钥的情况下,完成解密.这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险. 是由一对密钥来进行加解密的过程,分别称为公钥和 ...
- 调整PR界面字体大小
1.问题 界面字体太大或者太小,看得不舒服 2.解决问题 按住ctrl+F12,调出如下工作台 选择Debug Datatbase View 其中找到AdobeCleanFontSize,并修改 重启 ...
- 【Linux】技术收集
Linux进程间通信(六)---信号量通信之semget().semctl().semop()及其基础实验 https://blog.csdn.net/mybelief321/article/deta ...
- 你老了,别搞IT了……
你老了,别搞IT了-- [来源]
- PC 网页 布局图
- 如何部署两个JMS网关,形成双机热备
大家使用JMS的过程中,可能会留意到,不管是微服务在注册时,还是RemoteClient构造时,所指向的网关都是一个NetAddress数组,之所以网关地址是多个,而不是一个,那是因为网关是一个双击热 ...
- 【深入解读Redis系列】(五)Redis中String的认知误区,详解String数据类型
有时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,请认准https://blog.zysicyj.top 首发博客地址 系列文章地址 需求描述 现在假设有这样一个需求,我们要开发一个 ...