Codeforces Round 1002 (Div. 2)(A~D题题解)

A. Milya and Two Arrays

解析:我们发现c数组是由a和b数组累加来的,我们可以对a数组进行 随意的排序,因为a,b数组都是好数组,我们会发现只有三种情况满足最终的情况

1.a和b数组去重后的个数都等于2

2.a数组去重后的个数大于2,b数组可以任意

3.a数组任意,b数组去重后的个数大于2

这三种情况是满足最终结果的,只需要用一个set存储,去判断其size大小即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a;
int b; 
string s;
void solve()
{
	cin>>n;
	set<int> s1;
	set<int> s2;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
	    s1.insert(a);
	}
	for(int j=1;j<=n;j++)
	{
		cin>>b;
		s2.insert(b);
	}
	if((s1.size()==2&&s2.size()==2)||(s1.size()>2)||(s2.size()>2))
	{
		cout<<"YES\n";
	}
	else
	{
		cout<<"NO\n";
	}
}

signed main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	solve();
	return 0;
}

B. Cost of the Array

思路:我们可以发现最大的组内个数为n-k+1个,因此我们可以对其分情况讨论

1.首先当k<n时,我们可以看从2到n-k+2的情况

如果都是1,那么结果最终为2,我们可以将前,我们可以将2~n-k+作为一组,那么第二个一定为1,所以最终答案为2

如果不都是1,那么我们可以将不是1的数作为b数组的第一项,那么答案就是1

2.当n=k的情况,我们直接暴力就行

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a[200005];
string s;
void solve()
{
    cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}	
	if(k!=n)
	{
		int flag=0;
		for(int i=2;i<=2+n-k;i++)
		{
			if(a[i]!=1)
			{
				flag=1;
				break;
			}
		}
		if(flag==0)
		{
			cout<<2<<"\n";
		}
		else
		{
			cout<<1<<"\n";
		}
	}
	else
	{
		for(int i=2;i<=n;i+=2)
		{
			if(a[i]!=i/2)
			{
				cout<<i/2<<"\n";
				return;
			}
		}
		cout<<n/2+1<<"\n";
	}
}

signed main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	solve();
	return 0;
}

 C. Customer Service

 思路:一开始我想的是后缀和,但是发现自己想复杂了,我们还是用逆向思维,假设我们要让mex为2,那就说明有一行是这样的状态xxxxx1,如果要让mex为3,那就说明除了上述那一行,还要有一行的状态为xxxx11

因为每次都会删除一行为0,所以mex必然是大于0的,我t只需要用multise(无去重的set)统计每一行后缀1的个数即可,当我们后缀为1的数量大于等于mex的时候,就可以让mex的值++

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a[305][305];
void solve()
{
	cin>>n;
	multiset<int> s;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
		}
		int cnt=0;
		for(int j=n;j>=1;j--)
		{
			if(a[i][j]==1)
			{
				cnt++;
			}
			else
			{
				break;
			}
		}
		s.insert(cnt);
	}
	int mex=0;
	for(int u:s)
	{
		if(u>=mex)
		{
			mex++;
		}
	}
	cout<<mex<<"\n";
}

signed main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	solve();
	return 0;
}

D. Graph and Graph

思路: 对第三组数据手玩了一下,发现,只有当他们走到同一个点上,并且有一个边的顶点是相同的时候才会出现最小成本,否则就是无限大。因此我们可以用逆向思维来解决这个问题,我们可以先找到所有的可能出现的结果,然后逆向去bfs,我们让每个点只走一次,去寻找所有可能的出现的结果,如果遇到一图中的点为s1且二图中的点为s2的时候就立即更新结果,结束循环最终输出结果即可,我是用tuple去组成元组

不会的可以看博客详解tuple用法

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int s1,s2;
int m1,m2;
int ans=-1;
int d,u,v;
struct node{
	int d;
	int u1;
	int u2;
};
void solve()
{
	ans=-1;
	cin>>n>>s1>>s2; 
	cin>>m1;
	vector<int> e1[n+1];
	vector<pair<int,int>> edge1;
	for(int i=1;i<=m1;i++)
	{
		cin>>u>>v;
		e1[u].push_back(v);
		e1[v].push_back(u);
		pair<int,int> p=make_pair(u,v);
		edge1.push_back(p);
	}
	cin>>m2;
	vector<int> e2[n+1];
	vector<pair<int,int>> edge2;
	for(int i=1;i<=m2;i++)
	{
		cin>>u>>v;
		e2[u].push_back(v);
		e2[v].push_back(u);
		pair<int,int> p=make_pair(u,v);
		edge2.push_back(p);
	}
	priority_queue<tuple<int, int, int>,vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> que;
	for(pair<int,int> p1:edge1)
	{
		for(pair<int,int> p2:edge2)
		{
			int u1=p1.first;
			int v1=p1.second;
			int u2=p2.first;
			int v2=p2.second;
			if(u1==u2&&v1==v2)
			{
				que.push((tuple<int,int,int>){0,u1,u1});
			}
			if(u1==v2&&v1==u2)
			{
				que.push((tuple<int,int,int>){0,u1,u1});
			}
		}
	}
	vector<vector<int>> vis(n + 1, vector<int>(n + 1, 0));
	
	while(!que.empty())
	{
		tuple<int,int,int> tu=que.top();
		que.pop();
		d=get<0>(tu);
		u=get<1>(tu);
		v=get<2>(tu);
		if(vis[u][v]==1)
		continue;
		if(u==s1&&v==s2)
		{
			ans=d;
			break;
		}
		vis[u][v]=1;
		d+=abs(u-v);
		for(int u2:e1[u])
		{
			for(int v2:e2[v])
			{
				que.push(tuple<int,int,int>(d,u2,v2));
			}
		} 
	}
	cout<<ans<<"\n";
}

signed main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值