2021牛客暑期多校训练营10,签到题FH
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营10,签到题FH相关的知识,希望对你有一定的参考价值。
题号 标题 已通过代码 通过率 团队的状态
A Browser Games 点击查看 93/1498 未通过
B Child’s play 点击查看 0/8 未通过
C Dance Party 点击查看 10/343 未通过
D Diameter Counting 点击查看 26/73 未通过
E More Fantastic Chess Problem 点击查看 3/30 未通过
F Train Wreck 点击查看 699/2804 通过
G Game of Death 点击查看 41/103 未通过
H War of Inazuma (Easy Version) 点击查看 1272/3827 通过
I War of Inazuma (Hard Version) 点击查看 6/501 未通过
J Illuminations 点击查看 25/335 未通过
K Walking 点击查看 3/49 未通过
H War of Inazuma
题意:
- 定义n维超立方体有2^n个点,编号[0, 2^n-1], 点i和j相邻当且仅当2进制下仅有一位不同。
- 给出n,求构造长为2^n的01序列代表2^n个点,0表示抵抗军,1表示将军军,满足相邻的一侧不能大于sqrt(n),。
思路:
- 可以发现n维超立方体是一个二分图,直接按照二进制表示中1出现次数的奇偶
性进行黑白染色即可,时间复杂度O(2^n*n)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; scanf("%d", &n);
for(int i = 0; i < (1<<n); i++) //[0,2^n)
printf("%d",__builtin_popcount(i)&1);//返回输入数据二进制中1的个数
return 0;
}
F Train Wreck
题意:
- 给出长为2n的括号序列,()分别表示放入站台和拿出,以及n辆火车的颜色。
- 求构造一个放入序列,满足不存在同一时刻站台内的颜色序列相同
思路:
- 将栈操作视为树,要求转化为给每一个节点染色,使得从根到每一个节点的链所构
成的颜色序列两两不同。注意到两个都在第i 层的节点,如果它们的父亲不同,则从根
到它们父亲的链所构成的颜色序列不同,这使得从根到它们的链所构成的颜色序列一定
不同。(因为删去序列最后一项后得到的序列不同) - 因此,条件可以转化为每个点的k个儿子颜色互不相同。对于一个节点,假设其有k 个儿子,我们选取剩余火车数最多的k 个颜色对应上去即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
vector<int>G[maxn];
int fa[maxn], tot=1;
int a[maxn], ans[maxn];
int main(){
int n; string s; cin>>n>>s;
int p = 1;
for(char ch : s){//建树
if(ch=='('){
G[p].push_back(++tot);
fa[tot] = p;
p = tot;
}else{
p = fa[p];
}
}
for(int i = 1; i <= n; i++){
int x; cin>>x; a[x]++;
}
priority_queue<pair<int,int> >q;
for(int i = 1; i <= n; i++)q.push({a[i],i});
for(int i = 1; i <= tot; i++){ //枚举每个点
vector<pair<int,int> >vc; //备个份
for(int j = 0; j < G[i].size(); j++){//每个点的k个儿子颜色互不相同
auto p = q.top(); q.pop();
vc.push_back(p);
ans[G[i][j]] = p.second;//剩余火车数最多的k个颜色对应上去即可
if(p.first==0){
cout<<"NO\\n"; return 0;
}
}
for(auto p : vc){
p.first--; q.push(p);
}
}
cout<<"YES\\n";
for(int i = 2; i <= n+1; i++)
cout<<ans[i]<<" ";
return 0;
}
- 对于序列,每次放入会产生一个新的序列,我们用 [序列长度(链的长度), 序列最后一个元素放入时刻(即父亲)] 表示当前序列的状态,如果前面出现过这个序列,那就把新时刻加入末位,否则新建序列。
- 对于颜色,每次从当前剩余最多的开始取,每种颜色取一个,取出后按照顺序填入序列即可,可以用优先队列维护当前每种颜色的个数。
//比赛
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
map<int,int>ma;
map<pair<int,int>,int>mp;
vector<int>vc[maxn];
int ans[maxn];
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n; string s; cin>>n>>s;
for(int i = 1; i <= n; i++){
int x; cin>>x; ma[x]++;
}
stack<int>stk;
stk.push(0);
int t = 0, y = 0;
for(char ch : s){
if(ch=='('){
pair<int,int>p = make_pair(stk.size(), stk.top());
if(!mp[p])mp[p]=++t;
vc[mp[p]].push_back(++y);
stk.push(y);
}else{
stk.pop();
}
}
priority_queue<pair<int,int>>q;
for(auto i: ma)q.push({i.second, i.first});
for(int i = 1; i <= n; i++){
queue<pair<int,int> >nq;
for(int x : vc[i]){
if(q.empty()){
cout<<"NO\\n"; return 0; //颜色不够了
}
auto p = q.top(); q.pop();
if(p.first-1>0)nq.push({p.first-1,p.second});
ans[x] = p.second;
}
while(!nq.empty())q.push(nq.front()),nq.pop();
}
cout<<"YES\\n";
for(int i = 1; i <= n; i++)cout<<ans[i]<<" ";
return 0;
}
以上是关于2021牛客暑期多校训练营10,签到题FH的主要内容,如果未能解决你的问题,请参考以下文章