C. Game Master(思维 + 简单dfs)

Problem - C - Codeforces

 N个玩家在玩一个游戏。游戏中有两个不同的地图。对于每个玩家,我们都知道他们在每张地图上的实力。当两名玩家在一张特定地图上战斗时,在该地图上力量较高的玩家总是获胜。没有两名玩家在同一张地图上拥有相同的实力。你是游戏大师,想要组织一场比赛。总共会有n-1场战斗。当比赛中有不止一名玩家时,选择任意一张地图,任意两名剩下的玩家在上面战斗。输掉比赛的选手将被淘汰出局。最后,只有一名选手会留下来,他被宣布为比赛的冠军。每位选手决定他是否能赢得比赛。输入第一行包含一个整数t (1 <t< 100)——测试用例的数量。测试用例的描述如下。每个测试用例的第一行包含一个整数n (1 <n < 105)——玩家的数量。每个测试用例的第二行包含n个整数a1, a2,, an (1 < ai < 10°,ai a;对于I j),其中a;是第一张地图上第i个玩家的实力。每个测试用例的第三行包含n个整数b1, b2, ., bn (1 <b;< 109, b;b;对于I j),其中b;是第二张地图上第i个玩家的实力。它保证所有测试用例的n和不超过105。输出对于每个测试用例打印一个长度为n的字符串,如果第i个玩家能够赢得比赛,第i个字符应该是“1”,否则是“O”。

Example

input

Copy

3
4
1 2 3 4
1 2 3 4
4
11 12 20 21
44 22 11 30
1
1000000000
1000000000

output

Copy

0001
1111
1

题解:
首先我们可以知道一个地图上,力量最大的一定可以获得最终胜利,不需要在另一张图上比较了,

假设玩家1,2,如果某张地图1可以战胜2,连接一条2到1的边,如果2最终可以获得胜利,那么1肯定也可以获得胜利

因此我们把每张图的力量按从大到小排序,连接一条条i <- i + 1的有向的

并且从某张地图最大力量id开始遍历,要是遍历过,代表此id可以赢得游戏

#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
int a[100050];
int b[100050];
int id[100050];
vector<int> p[100050];
int vis[100050];
int cmpa(int x,int y)
{
	return a[x] > a[y];
}
int cmpb(int x,int y)
{
	return b[x] > b[y];
}
void dfs(int x)
{
	if(vis[x])
	return ;
	vis[x] = 1;
	for(auto ne:p[x])
	{
		if(!vis[ne])
		dfs(ne);
	}
}
void solve() 
{
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i = 1;i <= n;i++)
	{
		scanf("%d",&b[i]);
	}
	for(int i = 1;i <= n;i ++)
	{
		p[i].clear();
		id[i] = i;
		vis[i]  = 0;
	}
	sort(id+1,id + 1 + n,cmpa);
	for(int i = 1;i < n;i++)
	{
		p[id[i + 1]].push_back(id[i]);
	}
	sort(id + 1,id + 1 + n,cmpb);
	for(int i = 1;i < n;i++)
	{
		p[id[i + 1]].push_back(id[i]); 
	}
	dfs(id[1]);
	for(int i = 1;i <= n;i++)
	{
		if(vis[i])
		printf("1");
		else
		printf("0");
	}
	printf("\n");
}
 
//1 2 4
signed main() 
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
//	cin >> t;
    scanf("%d",&t);
	while (t--) 
	{
		solve();
	}
	return 0;
}
//1 1 1 0 1
 
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//0 1 1 1 1
//0 1 1 1 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值