【CF1428D】Bouncing Boomerangs 题解
题意简介
毒瘤大模拟
给你一张n*n的图,在图上摆有一些物体。从每一列的底端往上扔回旋镖,每镖中一个东西,回旋镖就会向右转九十度。现在我们知道从每列i底端往上镖时撞上的物体个数ai,试构造出一个合法的图。若无法构造出这样的图,输出-1。

需要注意的是,题目有几个重要的约束条件:
- \(a_i\leq3\)
- 每一行和每一列上的物品的个数不能超过2
思路分析
以下纯属个人看法。
要构造出一种符合题意的图,我们希望在构造过程中消耗的行和列尽可能少。
换句话说,我们希望能尽可能实现物体的“共用”。因为共用的话就不需要再开一行、一列了。
接下来考虑什么样的情况可以“共用”。我们令 \(i<j\) :
- \(a_j=1\) 时,若 \(a_i>1\) 则j所需要的物品可以与i共用。
- \(a_j=2\) 时,若 \(a_i>2\) 则j所需要的第一个物品可以与i共用。需要注意 \(a_i=2\) 的情况是不行的,因为每行最多只能有两个物体。
- \(a_j=3\) 时,若 \(a_i=3\) 则j所需要的第一个物品可以与i共用。需要注意出现在后面的3是不可能与前面的2共用的,因为若共用,只可能共用2的第二个物体,而这个物体与2的第一个物体在同一行上,若共用的话会撞上它,有 \(a_j>3\) ,不满足题意。
接下来考虑各种情况对空余行和列的数量的影响:
(下面的分析主要取决于影响的统计顺序,不同的统计方式可能会有不同的结论,此处只列出我的做法)
- \(a_j=0\) 时,空余列减1,因为这一列上不能放任何东西
- \(a_j=1\) 时,若与前面的某个i“共用”一个物体,由于已经在i处统计过了,所以不用重复统计影响;若没有共用,则空余行、空余列都要减1。因为我们是往右扫的,\(a_j=1\) 意味着这一行后面没有撞上东西。至于列,由于前面没有共用,且回旋镖只会往右转且最多打到3个物体,所以后面不可能再有某个k与这个j共用了。
- \(a_j=2\) 时,若与前面的某个i共用,\(a_i\) 一定等于3,由于已经在i处统计过了,所以只需空余列减1;若没有共用,则空余行减1、空余列减2。
- \(a_j=3\) 时,若与前面的某个i共用,\(a_i\) 一定等于3,由于已经在i处统计过了,所以只需空余行减1且空余列减1;若没有共用,则空余行减2、空余列减2
其实只要画个图,上面这些结论都可以很快得出。
一轮扫描,先确定每一个回旋镖的共用(拼接)顺序。假若扫描后出现空余列或空余行比0小的情况,就直接输出-1即可。
接下来需要考虑如何根据拼接顺序还原图。
我们知道,每个 \(a_i=2\) 后面必然且只能接一个 \(a_j=1\) ,接2或3的话会使 \(a_i=3\) 。
对于 \(a_i=3\) 的情形,我们需要的行数是最多的,所以我们不妨把这样的物体从最顶行设起。
对于 \(a_i=2 or a_i=1\) 的情形,我们不需要在行的下面再放物品了,不妨从最底行设起,把上面广阔的空间留给需要预留出一行的3。
注意观察图片 最顶行是1 最底行是n
下面给出几组我错过的数据可供测试(如果懒得去cf翻的话) 答案可以自己手推一下合不合理。
数据1:
4
3 3 1 1
数据2:
4
3 3 3 1
其实我主要是错在对行列处理的分类讨论上 还有对3的行分配上。这是需要注意的。
接下来就是实现,具体的一些小细节在代码中有体现,此处不再做赘述。
代码库
#include <cstdio>
const int N=1e5+5;
int n,a[N],pre[N],st2[N],st3[N],s2,s3,line,col,nex[N];
int ans[N<<1][2],cnt; bool vis[N];
inline bool is1(int i){
if(nex[i]) return a[nex[i]]!=3;
return a[i]==1;
}
int main(){
scanf("%d",&n); line=col=n;
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<=n;i++){
if(a[i]==0){
col--; continue;
}
if(a[i]==1){
if(s2) pre[i]=st2[s2--],nex[pre[i]]=i;
else if(s3) pre[i]=st3[s3--],nex[pre[i]]=i;
else line--,col--;
continue;
}
if(a[i]==2){
if(s3) pre[i]=st3[s3--],nex[pre[i]]=i,col--,st2[++s2]=i;
else line--,col-=2,st2[++s2]=i;
continue;
}
if(a[i]==3){
if(s3) pre[i]=st3[s3--],nex[pre[i]]=i,line--,col--,st3[++s3]=i;
else line-=2,col-=2,st3[++s3]=i;
continue;
}
}
if(line<0||col<0){
printf("-1\n"); return 0;
}
int top=0,low=n+1;
for(int i=1;i<=n;i++){
if(vis[i]||!a[i]) continue;
for(int j=i;j;j=nex[j]){
//printf("Calc %d:%d %d\n",j,top,low);
vis[j]=1;
if(a[j]==1){
if(!pre[j]) ans[++cnt][0]=--low,ans[cnt][1]=j;
//printf("Calc %d:%d %d\n",j,top,low);
continue;
}
if(a[j]==2){
if(!pre[j]){
if(is1(j)) ans[++cnt][0]=--low,ans[cnt][1]=j;
else ans[++cnt][0]=++top,ans[cnt][1]=j;
}
cnt++;
ans[cnt][0]=ans[cnt-1][0]; ans[cnt][1]=nex[j];
//printf("Calc %d:%d %d\n",j,top,low);
continue;
}
if(a[j]==3){
if(!pre[j]){
if(is1(j)) ans[++cnt][0]=low-2,ans[cnt][1]=j;
else ans[++cnt][0]=++top,ans[cnt][1]=j;
}
cnt++;
ans[cnt][0]=ans[cnt-1][0]; ans[cnt][1]=nex[j];
cnt++;
if(!pre[j]&&is1(j)) ans[cnt][0]=--low,ans[cnt][1]=nex[j],low--;
else if(is1(j)) ans[cnt][0]=--low,ans[cnt][1]=nex[j];
else ans[cnt][0]=++top,ans[cnt][1]=nex[j];
//printf("Calc %d:%d %d\n",j,top,low);
continue;
}
}
}
//printf("End with %d %d\n",top,low);
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++) printf("%d %d\n",ans[i][0],ans[i][1]);
//for(int i=1;i<=n;i++) if(a[i]!=1&&a[i]!=0&&nex[i]==0) printf("ERR %d!\n",i);
return 0;
}
END
【CF1428D】Bouncing Boomerangs 题解的更多相关文章
- 算法与数据结构基础 - 哈希表(Hash Table)
Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- Codeforces Round#687 Div2 题解
打这场的时候迷迷糊糊的,然后掉分了( A Prison Break: 题面很复杂,但是题意很简单,仅需求出从这个点到四个角的最大的曼哈顿距离即可 #include <bits/stdc++.h& ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- [LeetCode] Number of Boomerangs 回旋镖的数量
Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of po ...
- 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 只做出来四道比较水的题目,还需要加强中等题的训练 ...
随机推荐
- 基于jQuery的鼠标悬停时放大图片的效果制作
这是一个基于jQuery的效果,当鼠标在小图片上悬停时,会弹出一个大图,该大图会跟随鼠标的移动而移动.这个效果最初源于小敏同志的一个想法,刚开始做的时候只能实现弹出的图片是固定的,不能随鼠标移动,最后 ...
- Linux搭建SonarQube
环境:linux+jdk8+mysql5.7.31+sonarqube7.5+sonar-scanner-4.4+jenkins2.249+sonar-l10n-zh-plugin-1.25.jar ...
- oracle之三rman 维护
rman 维护 11.1 rman 使用和维护 11.2 list 命令一览 1)RMAN> list backup; 2)RMAN> list backup of tablespace ...
- 软件测试----xml文件介绍
软件测试 目录 软件测试 一.什么是XML?: 二.XML和HTML的差异: 三.XML的特点 1.XML可以自定义标签 2.XML必须包含根元素 如上所示, 3.XML标签对大小写敏感 4.XML ...
- github无法访问
打开 C:\Windows\System32\Drivers\etc 找到hosts文件. 添加以下代码 #github 192.30.255.112 github.com git 185.31.16 ...
- Docker日志管理–docker部署安装ELK (十一)
Docker logs 对于一个运行的容器,Docker 会将日志发送到 容器的 标准输出设备(STDOUT)和标准错误设备(STDERR),STDOUT 和 STDERR 实际上就是容器的控制台终端 ...
- 突发!美商务部宣布封禁微信,TikTok——面对科技封锁,如何应对
刚刚美国商务部忽然发布了这则新闻,为了回应特朗普2020年8月6号的行政令,称这些应用程序存在安全威胁. 禁令中称,自2020年9月20日起,美国政府将: 1 禁止通过美国在线移动应用程序商店分发或维 ...
- k8s Docker 安装
k8s Docker 安装 一.运行环境 Centos 7.7 虚拟机内核为 3.10 基础组件版本: k8s.gcr.io/kube-apiserver:v1.16.0 k8s.gcr.io/kub ...
- Qt 展示pdf内容(新窗口或嵌入,pdfjs,linux)
前言:初学Qt,在网上查找了诸多资料,有什么poppler.mupdf啊巴拉巴拉的,结果一个比一个费劲,最后还是采用pdfjs较为方便高效,为方便相关问题搜索,写了一下内容. 需求描述:Qt应用中不支 ...
- 执行引擎(Execution Engine)基础知识
概述 执行引擎是Java虚拟机的核心组成部分之一 虚拟机是一个相对于"物理机"的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.缓存.指令集和操作系统 ...