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的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营1, 签到题DFBG

2021牛客暑期多校训练营2,签到题CDFKI

2021牛客暑期多校训练营7,签到题FHI

2021牛客暑期多校训练营6,签到题CFHI

2021牛客暑期多校训练营5,签到题BDHJK

2021牛客暑期多校训练营4,签到题CFIJ