【Comet OJ - Contest #5 - C】迫真小游戏(优先队列,贪心构造,树,字典序)

题干:

H君喜欢在阳台晒太阳,闲暇之余他会玩一些塔防小游戏。

H君玩的小游戏可以抽象成一棵 nn 个节点的有根树,树以 11 为根,每个点的深度定义为其到根的简单路径上的点数(根的深度为 11)。

H君有 nn 个干员,H君会按照某种顺序把她们部署到树的每一个节点上,使得每个节点上恰好有一个干员。由于游戏的机制,他们对每个节点 ii 都给出了个限制参数 a_iai​ ,要求H君在第 ii 个节点部署干员之前,所有深度 > a_i>ai​ 的节点上不能有干员。同时游戏为了让玩家过关,保证了 a_iai​ 大于等于点 ii 的深度。

H君将每一次部署干员的节点按顺序写在纸上,形成了一个 1 \dots n1…n 的排列,H君为了获得更多的奖励,想要最小化这个排列的字典序。

我们认为排列 c_1,c_2..c_nc1​,c2​..cn​ 的字典序比排列 d_1,d_2..d_nd1​,d2​..dn​ 的字典序小,当且仅当 c, dc,d 不完全相同且存在一个下标 ii,满足 c_i < d_ici​<di​ 且对于所有 1 \le j < i1≤j<i 的 jj 都有 c_j = d_jcj​=dj​ 。

输入描述

第一行一个数 nn 。

接下来 n - 1n−1 行,每行两个数 x, yx,y 表示树上的一条边 。

最后一行 nn 个数,表示 a_iai​ 。

数据范围:

1\le n \le 5 \times 10^5, 1 \le a_i \le n1≤n≤5×105,1≤ai​≤n。

输出描述

第一行 nn 个数,表示字典序最小的排列。

样例输入 1 

5
1 5
5 3
1 4
4 2
1 3 3 3 2

样例输出 1

1 4 5 2 3

样例输入 2 

10
1 7
7 8
7 2
8 9
7 6
2 4
9 5
8 10
6 3
5 3 4 4 5 3 5 3 5 4

样例输出 2

1 2 6 7 8 3 4 9 10 5

解题报告:

考虑贪心的策略。首先根据给定的a数组排序,因为这样的话,是限制逐步增加的情况,同时可选择的元素逐步增多,所以可以考虑同时用优先队列动态维护可以“写在纸上”的元素。

按照这个想法,我们可以一个一个构造。首先肯定是深度小于在排好序后最小的a的那些点都可以“写在纸上”,我们把可以“写在纸上”的候选点都放到优先队列中。考虑什么时候可以扩展优先队列中的元素呢?也就是你把第i号点写在纸上了之后,才能有更多候选点,所以每次扩展之后就把优先队列中所有 编号小于第i号点的编号 的那些点都“写在纸上”。然后重复上述操作就好。这也是为什么要求字典序最小,因为这样就可以使得所有候选点中标号小于i的编号的那些点,可以优先扩展出来,比先扩展i编号的节点更优。

其实这题的核心就是用优先队列动态维护可以“写在纸上”的候选点,优先级是编号最小。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 5e5 + 5;
int n,a[MAX];
struct Node {int a,id;
} R[MAX],D[MAX];
bool cmp(Node a,Node b) {return a.a != b.a ? a.a < b.a : a.id < b.id;}
vector<int> vv[MAX],ans;
void dfs(int cur,int fa) {D[cur].a = D[fa].a + 1;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v != fa) dfs(v,cur);}	
}
int vis[MAX];
int main()
{cin>>n;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i,D[i].id = i;dfs(1,0); sort(R+1,R+n+1,cmp); sort(D+1,D+n+1,cmp);priority_queue<int,vector<int>,greater<int> > pq;int cur = 1;for(int i = 1; i<=n; i++) {if(vis[R[i].id]) continue;while(D[cur].a <= R[i].a && cur <= n) {pq.push(D[cur].id);cur++;}while(pq.size() && pq.top() <= R[i].id) ans.pb(pq.top()),vis[pq.top()] = 1,pq.pop();}for(int x : ans) {printf("%d ",x);}return 0 ;
}

错误代码1:

错误原因,刚开始就是这样写的,想法就是找到最小的a的那个编号id(假设此时决策的id是idd),所有深度小于等于idd的都先“写到纸上”。但是其实是不对的,因为你需要看的是编号也小于idd的。因为编号如果大于idd的话那肯定要先写idd,但是写idd的话就会解锁这一层封印,所以写完idd之后下一个写的不一定是此时候选点中编号大于idd的那些点,也有可能是解除封印后又有编号更小的点了;而编号小于idd的可以直接写到纸上,因为你是按a排序的,所以不需要担心写idd之后会解锁新东西。因为就算是解锁新东西了也不能加入到候选点中,因为idd还没有写,所以无法解封那些。

int main()
{cin>>n;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i,D[i].id = i;dfs(1,0); sort(R+1,R+n+1,cmp); sort(D+1,D+n+1,cmp);priority_queue<int,vector<int>,greater<int> > pq;int cur = 1;for(int i = 1; i<=n; i++) {while(D[cur].a <= R[i].a && cur <= n) {pq.push(D[cur].id);cur++;}while(pq.size()) ans.pb(pq.top()),pq.pop();} for(int x : ans) {printf("%d ",x);}return 0 ;
}

错误代码2:

因为其实你vis数组不是用来在输出的时候去重用的,而是用来看省去下面的判断的。

int vis[MAX];
int main()
{cin>>n;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i,D[i].id = i;dfs(1,0); sort(R+1,R+n+1,cmp); sort(D+1,D+n+1,cmp);priority_queue<int,vector<int>,greater<int> > pq;int cur = 1;for(int i = 1; i<=n; i++) {
//		if(vis[R[i].id]) continue;while(D[cur].a <= R[i].a && cur <= n) {pq.push(D[cur].id);cur++;}while(pq.size() && pq.top() <= R[i].id) ans.pb(pq.top()),pq.pop();}for(int x : ans) {if(vis[x]) continue;printf("%d ",x);vis[x] = 1;}return 0 ;
}

改成这样就可以AC了:

int main()
{cin>>n;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i,D[i].id = i;dfs(1,0); sort(R+1,R+n+1,cmp); sort(D+1,D+n+1,cmp);priority_queue<int,vector<int>,greater<int> > pq;int cur = 1;for(int i = 1; i<=n; i++) {
//		if(vis[R[i].id]) continue;while(D[cur].a <= R[i].a && cur <= n) {pq.push(D[cur].id);cur++;}if(vis[R[i].id]) continue;while(pq.size() && pq.top() <= R[i].id) ans.pb(pq.top()),vis[pq.top()] = 1,pq.pop();}for(int x : ans) {printf("%d ",x);}return 0 ;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手学无人驾驶(1):交通标志识别

今天主要介绍无人驾驶当中深度学习技术的应用。 本文是根据博客专家AdamShan的文章整理而来&#xff0c;在此表示感谢。 关于深度学习的图像分类技术&#xff0c;网上已有很多关于深度学习的课程&#xff08;如吴恩达老师的深度学习专项课程&#xff09;&#xff0c;故本文不对…

《操作系统真象还原》-阅读笔记(上)

第一章 配置bochs&#xff0c;进入bochs simulator后一直是黑屏&#xff0c;原来默认是调试模式&#xff0c;需要输入C&#xff08;continue&#xff09;来让调试继续。 第二章 主讲MBR及进入MBR前的步骤 1.实模式只能访问1MB的内存空间。 2.BIOS在ROM中。 3.开机上电后CS&a…

Apollo进阶课程㉟丨Apollo ROS原理—4

原文链接&#xff1a;进阶课程㉟丨Apollo ROS原理—4 ROS是一个强大而灵活的机器人编程框架&#xff0c;从软件构架的角度说&#xff0c;它是一种基于消息传递通信的分布式多进程框架。 ROS本身是基于消息机制的&#xff0c;可以根据功能把软件拆分成为各个模块&#xff0c;每…

【HDU - 5917】Instability(规律,结论,Ramsey定理,知识点,tricks)

题干&#xff1a; Long long ago, there was a prosperous kingdom which consisted of n cities and every two cites were connected by an undirected road. However, one day a big monster attacked the kingdom and some roads were destroyed. In order to evaluate th…

《操作系统真象还原》-阅读笔记(中)

第七章 操作系统是由中断驱动的。 中断分为外部中断和内部中断。 外部中断分为可屏蔽中断和不可屏蔽中断&#xff0c;内部中断分为软中断和异常。 外部中断 来自CPU外部的中断。可屏蔽中断&#xff1a;通过INTR引脚进入CPU&#xff0c;外部设备如硬盘、网卡、打印机等发出的…

动手学无人驾驶(2):车辆检测

上一篇博客介绍了无人驾驶中深度学习在交通标志识别中的应用&#xff08;动手学无人驾驶&#xff08;1&#xff09;&#xff1a;交通标志识别&#xff09;。 本文介绍如何使用深度学习进行车辆检测&#xff0c;使用到的模型是YOLO模型&#xff0c;关于YOLO模型的具体检测原理&a…

【HDU - 5922】Minimum’s Revenge(思维,最小生成树变形)

题干&#xff1a; There is a graph of n vertices which are indexed from 1 to n. For any pair of different vertices, the weight of the edge between them is the least common multiple of their indexes. Mr. Frog is wondering about the total weight of the minim…

《操作系统真象还原》-阅读笔记(下)

第十一章 任意进程的页目录表第0~767个页目录项属于用户空间&#xff0c;指向用户页表。第768~1023个页目录项指向内核页表。每创建一个新的用户进程,就将内核页目录项复制到用户进程的页目录表&#xff0c;其次需要把用户页目录表中最后一个页目录项更新为用户进程自己的页目…

Apollo进阶课程㊱丨Apollo ROS深入介绍

原文链接&#xff1a;进阶课程㊱丨Apollo ROS深入介绍 ROS是一个强大而灵活的机器人编程框架&#xff0c;从软件构架的角度说&#xff0c;它是一种基于消息传递通信的分布式多进程框架。ROS本身是基于消息机制的&#xff0c;可以根据功能把软件拆分成为各个模块&#xff0c;每…

一步步编写操作系统 31 cpu的分支预测 下

让我们说说预测的算法吧。 对于无条件跳转&#xff0c;没啥可犹豫的&#xff0c;直接跳过去就是了。所谓的预测是针对有条件跳转来说的&#xff0c;因为不知道条件成不成立。最简单的统计是根据上一次跳转的结果来预测本次&#xff0c;如果上一次跳转啦&#xff0c;这一次也预…

【HDU - 5493】Queue(思维,贪心,线段树)

题干&#xff1a; NN people numbered from 1 to NN are waiting in a bank for service. They all stand in a queue, but the queue never moves. It is lunch time now, so they decide to go out and have lunch first. When they get back, they don’t remember the exa…

Apollo进阶课程㊲丨Apollo自动驾驶架构介绍

原文链接&#xff1a;进阶课程㊲丨Apollo自动驾驶架构介绍 自动驾驶硬件架构&#xff1a;一般采用激光雷达作为主要感知传感器&#xff0c;同时结合摄像头、GPS/IMU、毫米波雷达、超声波雷达等&#xff0c;以NVIDIA Drive PX2 或 Xavier作为主要计算平台&#xff0c;在工业PC机…

一步步编写操作系统 32 linux内核获取内存容量的方法

操作系统是计算机硬件的管家&#xff0c;它不仅要知道自己的安装了哪些硬件&#xff0c;还得给出有效得当的管理措施&#xff0c;按照预定的一套管理策略使硬件资源得到合理的运用。但管理策略只是逻辑上的东西&#xff0c;是操作系统自圆其说的一套管理资源的方法&#xff0c;…

【HDU - 5489】Removed Interval(离散化,权值线段树,思维,最长上升子序列)

题干&#xff1a; Given a sequence of numbers Aa1,a2,…,aNAa1,a2,…,aN, a subsequence b1,b2,…,bkb1,b2,…,bk of AA is referred as increasing if b1<b2<…<bkb1<b2<…<bk. LY has just learned how to find the longest increasing subsequence (LI…

Apollo进阶课程㊳丨Apollo平台的快速入门

原文链接&#xff1a;进阶课程㊳丨Apollo平台的快速入门 Apollo是向汽车行业及自动驾驶领域的合作伙伴提供一个开放、完整、安全的软件平台&#xff0c;帮助他们结合车辆和硬件系统&#xff0c;快速搭建一套属于自己的完整的自动驾驶系统。 上周阿波君为大家详细介绍了「进阶课…

一步步编写操作系统 33 利用bios中断0x15子功能0xe820获取内存

咱们先介绍0xE820子功能&#xff0c;这是最灵活的内存获取方式。 bios中断 0x15的子功能0xE820能够获取系统的内存布局&#xff0c;由于系统内存各部分的类型属性不同&#xff0c;bios就按照类型属性来划分这片系统内存&#xff0c;所以这种查询则呈迭代式&#xff0c;每次bio…

16.深度学习练习:Building your Recurrent Neural Network - Step by Step

本文节选自吴恩达老师《深度学习专项课程》编程作业&#xff0c;在此表示感谢。课程链接&#xff1a;https://www.deeplearning.ai/deep-learning-specialization/Building your Recurrent Neural Network - Step by Step1 - Forward propagation for the basic Recurrent Neur…

【2019icpc徐州站】Random Access Iterator(概率dp,有坑,tricks)

题干&#xff1a; Recently Kumiko learns to use containers in C standard template library. She likes to use the std::vector very much. It is very convenient for her to do operations like an ordinary array. However, she is concerned about the random-access…

一步步编写操作系统 34 内核利用bios中断获取物理内存大小

接上文&#xff0c;另一个获取内存容量的方法是bios 0x15中断的子功能0xE801。 此方法虽然简单&#xff0c;但功能也不强大&#xff0c;最大只能识别4G内存&#xff0c;不过这对咱们32位地址总线足够了。稍微有点不便的是&#xff0c;此方法检测到的内存是分别存放到两组寄存器…

【HDU - 5777】domino(贪心)

题干&#xff1a; Little White plays a game.There are n pieces of dominoes on the table in a row. He can choose a domino which hasnt fall down for at most k times, let it fall to the left or right. When a domino is toppled, it will knock down the erect dom…