迫真小游戏

已经提交 已经通过 时间限制:2000ms 内存限制:256MB

73.98%

提交人数:196

通过人数:145

题目描述

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

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

H君有 nn 个干员,H君会按照某种顺序把她们部署到树的每一个节点上,使得每个节点上恰好有一个干员。由于游戏的机制,他们对每个节点 ii 都给出了个限制参数 a_ia

i



,要求H君在第 ii 个节点部署干员之前,所有深度 > a_i>a

i



的节点上不能有干员。同时游戏为了让玩家过关,保证了 a_ia

i



大于等于点 ii 的深度。

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

我们认为排列 c_1,c_2..c_nc

1



,c

2



..c

n



的字典序比排列 d_1,d_2..d_nd

1



,d

2



..d

n



的字典序小,当且仅当 c, dc,d 不完全相同且存在一个下标 ii,满足 c_i < d_ic

i



<d

i



且对于所有 1 \le j < i1≤j<i 的 jj 都有 c_j = d_jc

j



=d

j



输入描述

第一行一个数 nn 。

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

最后一行 nn 个数,表示 a_ia

i



数据范围:

1\le n \le 5 \times 10^5, 1 \le a_i \le n1≤n≤5×10

5

,1≤a

i



≤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

题意:



思路:

首先dfs把整颗树跑一遍,得出每一个节点在第几层的信息,然后我们从1到n层扫一遍,对于每一层,我们把这一层上的所以节点操作,如果这个节点的a[i] 值是等于i的,那么这个节点在这一次操作中必须要部署,所以加入到一个大根堆中,否则加入到一个set中,同时用一个vector维护set中每一个a[i] 值加入了那些节点, 然后我们再从vector中查找是否有当前第i层的节点被介入到了set中,如果有就把它取出加入大根堆 ,然后把set的第一个元素(id最小的)与大根堆的堆顶(id最大的元素)比较,如果小于,就把它从set中取出,加入到堆中,一直这样操作,直到大于堆顶或者set为空,这样就可以使其字典序最小。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=6e5;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
std::vector<int> son[maxn];
int n;
int a[maxn];
int depth[maxn];
void dfs(int x,int pre)
{
depth[x]=depth[pre]+1;
for(auto y:son[x])
{
if(y!=pre)
{
dfs(y,x);
}
}
}
bool vis[maxn];
std::vector<int> ans;
struct node
{
int ai;
int id;
node(){}
node(int ii,int aai)
{
id=ii;
ai=aai;
}
friend bool operator < (node x,node y)
{
//set套结构体要重载<运算符
return x.id < y.id;
}
};
struct cmp
{
bool operator ()(const node p1,const node p2)
{
return p1.id>p2.id;// 以first为比较对象的小根堆
}
};
struct cmp2
{
bool operator ()(const node p1,const node p2)
{
return p1.id<p2.id;// 以first为比较对象的小根堆
}
};
std::vector<node> ceng[maxn];
set<node> xgd;
priority_queue<node,vector<node>,cmp2 > dgd;
std::vector<int> jia[maxn];
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin>>n;
int u,v;
repd(i,2,n)
{
cin>>u>>v;
son[v].pb(u);
son[u].pb(v);
}
repd(i,1,n)
{
cin>>a[i];
vis[a[i]]=1;
}
depth[0]=0;
dfs(1,0);
repd(i,1,n)
{
ceng[depth[i]].pb(node(i,a[i]));
}
repd(i,1,n)
{
for(auto x:ceng[i])
{
if(x.ai==i)
{
dgd.push(x);
}else
{
xgd.insert(x);
jia[x.ai].pb(x.id);
}
}
for(auto x:jia[i])
{
if(xgd.count(node(x,a[i]))==1)
{
xgd.erase(node(x,a[x]));
dgd.push(node(x,a[x]));
}
}
while((xgd.size()>0)&&(!dgd.empty())&&((*xgd.begin()).id<dgd.top().id))
{
dgd.push(*xgd.begin());
xgd.erase(xgd.begin());
}
std::vector<int> v;
v.clear();
while(!dgd.empty())
{
v.push_back(dgd.top().id);
dgd.pop();
}
reverse(ALL(v));
for(auto y:v)
ans.push_back(y);
} while(!xgd.empty())
{
ans.pb((*xgd.begin()).id);
xgd.erase(xgd.begin());
}
for(int i=0;i<ans.size();i++)
{
if(i!=0)
{
cout<<" "<<ans[i];
}else{
cout<<ans[i];
}
}
cout<<endl; return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

Comet OJ - Contest #5 D 迫真小游戏 (堆+set)的更多相关文章

  1. Comet OJ - Contest #5 E 迫真大游戏

    怎么说,看了推到之后真的不难,事实上确实也蛮友好(可能咱就是想不出多项式题目的做法???),除了用到了分治法法塔就比较毒瘤 花了一个晚上以及一个上午做这么一道题...(还是太菜了) Result1 分 ...

  2. Comet OJ - Contest #5 简要题解

    好久没更博了,还是象征性地更一次. 依然延续了简要题解的风格. 题目链接 https://cometoj.com/contest/46 题解 A. 迫真字符串 记 \(s_i\) 表示数字 \(i\) ...

  3. Comet OJ - Contest #2简要题解

    Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...

  4. Comet OJ - Contest #11 题解&赛后总结

    Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...

  5. Comet OJ - Contest #5

    Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下, ...

  6. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  7. Comet OJ - Contest #4--前缀和

    原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...

  8. Comet OJ - Contest #8

    Comet OJ - Contest #8 传送门 A.杀手皇后 签到. Code #include <bits/stdc++.h> using namespace std; typede ...

  9. Comet OJ - Contest #13-C2

    Comet OJ - Contest #13-C2 C2-佛御石之钵 -不碎的意志-」(困难版) 又是一道并查集.最近做过的并查集的题貌似蛮多的. 思路 首先考虑,每次处理矩形只考虑从0变成1的点.这 ...

随机推荐

  1. 微信小程序打印json log

    微信小程序中如果 res.data数据是一个json格式数据.console.log("===data===" + res.data);//如果这样打印出了是只会打印一个对象名称, ...

  2. Java第一次学习总结

    学习内容: 1.java是本学期刚刚接触新的一种编程语言,与大一C语言在语法上有很多相同之处,不同的是在很多问题上,更加简练,更加易于理解. 例如:输出水仙花数,从C语言近五十行代码缩短近十几行,数据 ...

  3. 将数据库中带出的列,在gridview中影藏起来

    前台增加事件:OnRowCreated="GridView1_RowCreated" protected void GridView1_RowCreated(object send ...

  4. Centos 建一个指定大小的文件夹

    1.使用ramdisklinux可以把一部分内存mount为分区使用,通常为称为ramdisk,分为ramdisk, ramfs, tmpfs.可以一条命令实现我们的需求:mount none tes ...

  5. 基于RANSAC的点云面分割算法

    该算法在RANSAC和空间检索树的基础上实现的. 算法思路: 1.点云抽希.法线估计 2.出局点索引存储声明 3.平面检测 for (size_t i = 0; i < cloudTemp-&g ...

  6. 安装Mantis出现的一些问题解决

    1.去除 Warning: date_default_timezone_get() 打开config_inc.php, 增加: $g_default_timezone = 'RPC'; 2.去除  S ...

  7. $apply()和$digest()——angular

    $apply()和$digest()在AngularJS中是两个核心概念,但是有时候它们又让人困惑.而为了了解AngularJS的工作方式,首先需要了解$apply()和$digest()是如何工作的 ...

  8. Java之Swing体系——制作自己的登录界面

    我们制作登陆界面是简单的图形模式,并不具备其他功能: 这里使用两个库,如下: javax.swing.*; java.awt.*; 构造窗体对象要用到很多类,废话不多,直接代码~ package co ...

  9. cocos2dx基础篇(8) 开关按钮CCControlSwitch

    [3.x] (1)去掉 “CC” (2)对象类 CCObject 改为 Ref (3)标签类 LabelTTF 改为 Label (4)CCControlEvent 改为强枚举 Control::Ev ...

  10. Java第三周课程总结&实验报告一

    第三周课程总结 1.关于面向对象的一些具体内容,明白了类与对象以及Java的封装性和构造方法以及对对象匿名的相关知识. 2.this关键字,它是表示类的成员属性(变量),使用this构造方法时必须放在 ...