Codeforces Round #835 (Div. 4) 题解 A-G

A 题目链接:https://codeforces.com/contest/1760/problem/A

 

input:

9
5 2 6
14 3 4
20 2 1
1 2 3
11 19 12
10 8 20
6 20 3
4 1 3
19 8 4

output:

5
4
2
2
12
10
6
3
8

题意:

给三个数,输出中间值。

思路:

sort 取第二个即可。

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int a[10];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>a[1]>>a[2]>>a[3];
		sort(a+1,a+4);
		cout<<a[2]<<endl;
	}
	return 0;
}

B 题目链接:https://codeforces.com/contest/1760/problem/B

input:

5
1
a
4
down
10
codeforces
3
bcf
5
zzzzz

output:

1
23
19
6
26

题意:

给一个小写字母字符串,输出其中最大的字母的数值( A ~ Z 对应 1 ~ 26 )。

思路:

开一个maxn变量,遍历字符串找最大值即可。

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		string s;
		cin>>s;
		int ans=0;
		for(int i=0;i<n;i++)
		{
			ans=max(ans,s[i]-96);
		}
		cout<<ans<<endl;
	}
	return 0;
}

C 题目链接:https://codeforces.com/contest/1760/problem/C

input:

5
4
4 7 3 5
2
1 2
5
1 2 3 4 5
3
4 9 4
4
4 4 4 4

output:

-3 2 -4 -2 
-1 1 
-4 -3 -2 -1 1 
-5 5 -5 
0 0 0 0 

题意:

给一个长度为 n 的数组 a ,对于每一个数,输出其与最大值的差,对于最大值本身,输出其与第二大值的差。

思路:

遍历一次找最大值,再遍历找与其的差值,最小的差值即为最大值本身要输出的数。最后遍历输出即可。

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int a[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int maxn=0;
		int k=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			if(a[i]>maxn)
			{
				maxn=a[i];
				k=i;
			}
		}
		int minn=0x3f3f3f3f;
		for(int i=1;i<=n;i++)
		{
			if(i==k)
				continue;
			else
			{
				minn=min(minn,a[k]-a[i]);
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i==k)
			{
				cout<<minn<<" ";
			}
			else
			{
				cout<<a[i]-a[k]<<" ";
			}
		}
		cout<<endl;
	}
	return 0;
}

D 题目链接:https://codeforces.com/contest/1760/problem/D

input:

6
7
3 2 2 1 2 2 3
11
1 1 1 2 3 3 4 5 6 6 6
7
1 2 3 4 3 2 1
7
9 7 4 6 9 9 10
1
1000000000
8
9 4 4 5 9 4 9 10

output:

YES
YES
NO
YES
YES
NO

题意:

给 n 个数的数组 a ,如果存在图中 “ 凹陷 ” 现象,输出 NO,否则输出 YES 。

思路:

如果记录到相邻两数存在上升现象时,每次记录较大值,此后如果记录到有数小于记录值,输出NO,遍历结束后若合法,输出YES

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int a[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		bool f=0,flag=1;
		int k=0;
		for(int i=1;i<n;i++)
		{
			if(a[i]<a[i+1])
			{
				f=1;
				k=a[i+1];
				continue;
			}
			if(f==1)
			{
				if(a[i+1]<k)
				{
					flag=0;
					break;
				}
			}
		}
		if(flag)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}

E 题目链接:https://codeforces.com/contest/1760/problem/E

input:

5
4
1 0 1 0
6
0 1 0 0 1 0
2
0 0
8
1 0 1 1 0 0 0 1
3
1 1 1

output:

3
7
1
13
2

题意:

给一个由 n 个 0,1组成的数组 a ,该数组的 inversions 指 下标大小关系与自身大小关系相反的元素对的数量。问最多可以操作一次,使某一位元素自相反。问修改(或不修改)得到的最大值是多少

思路:

贪心,只存在三种情况

1.不修改

2.修改从左往右第一个0

3.修改从右往左第一个1

三种情况比较最大值即可

inversions计算方式也很简单,就是每一个0前面所有1的总和

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

ll t,n;
int a[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		ll cnt1=0,cnt0=0;
		bool f=0;
		ll pos1=n+1,pos0=0;
		ll ans=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			if(a[i]==1)
			{
				cnt1++;
				pos1=i;
			}
			else
			{
				cnt0++;
				if(f==0)
				{
					f=1;
					pos0=i;
				}
				ans+=cnt1;
			}
		}
		ans=max(ans,ans+max(cnt0-1-pos0+1,cnt1-1-n+pos1));
		cout<<ans<<endl;
	}
	return 0;
}

F 题目链接:https://codeforces.com/contest/1760/problem/F

input:

6
2 5 4
1 2
2 20 10
100 10
3 100 3
7 2 6
4 20 3
4 5 6 7
4 100000000000 2022
8217734 927368 26389746 627896974
2 20 4
5 1

output:

2
Infinity
Impossible
1
12
0

题意:

有 n 种工作,每种工作做完可以获得 ai 元,每天只能完成一种工作。每做完一种工作, k 天内不能再做,给定 c 和 d ,意为在 d 天内获得 c 元,问能够接受最大的 k 约束是多少,输出 k 的值。如果不能约束,输出 “ Impossible ”  如果任意约束都能完成目标 ,输出 “ Infinity ”

思路:

贪心处理。先按价值从大到小排序,在限制条件下,我们一定是优先选最大的,限制解除后继续选最大的

首先看一下两种特殊情况处理

1. 如果说在不加限制的条件下,也就是每次选择价值最大的工作,完成 d 天,依然无法达成目标,那么可以输出 Impossible

2.如果说限制无限大,也就是说每种工作只能做一次,且总时间不超过 d 天的情况下,依然可以达成目标,那么可以输出 Infinity

3.正常情况下,直接二分答案k即可。对于一个限制 k ,我们的工作模式是 k + 1天的循环,取模每次做价值最大的工作即可(也有可能不工作),然后check判断当前 k 能不能达成目标

注意对价值序列进行前缀和化出力,能降一维复杂度

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

ll t,n,c,d;
ll a[N],s[N];
inline bool cmp(ll a,ll b)
{
	return a>b;
}

inline bool check(ll k)
{
	k++;
	ll time=d/k;
	ll m=d%k;
	if(time*s[min(k,n)]+s[min(m,n)]<c)
		return false;
	else
		return true; 
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n>>c>>d;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		sort(a+1,a+n+1,cmp);
		for(int i=1;i<=n;i++)
		{
			s[i]=s[i-1]+a[i];
		}
		if(a[1]*d<c)
		{
			cout<<"Impossible"<<endl;
			continue;
		}
		if(s[min(d,n)]>=c)
		{
			cout<<"Infinity"<<endl;
			continue;
		}
		ll l=0,r=d,mid=0;
		while(l<r)
		{
			mid=(l+r+1)>>1;
			if(check(mid))
			{
				l=mid;
			}
			else
			{
				r=mid-1;
			}
		}
		cout<<l<<endl;
	}
	return 0;
}

G 题目链接:https://codeforces.com/contest/1760/problem/G

input:

3
5 1 4
1 3 1
2 3 2
4 3 3
3 5 1
2 1 2
1 2 2
6 2 3
1 2 1
2 3 1
3 4 1
4 5 3
5 6 5

output:

YES
NO
YES

题意:

有一个 n 个点的树,每条边都有权值 w ,现在给定起点 a ,终点 b ,一开始 x = 0 ,每次由一个点到另一个点时 ,x与这条边的权值异或 ,问能否在到达 b 的时候 ,x = 0(有一次机会,可以从任意点跳到除点 b 外的任意点,不经过异或)

思路:

从点 a 开始 dfs ,每次进行异或,将当前异或值存入 set。

然后从点 b 开始 dfs ,每次进行异或,如果当前值能在 set 中 找到,那么输出YES

否则输出NO

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

struct node{
	ll f,w;
};
int t,n=0,a,b;
bool flag;

vector<node> vec[N];
set<ll> st;

void dfs_a(int from,int to,ll sum)
{
	if(to==b)
	{
		return;
	}
	st.insert(sum);
	for(auto &x:vec[to])
	{
		if(x.f==from)
			continue;
		dfs_a(to,x.f,sum^x.w);
	}
}

void dfs_b(int from,int to,ll sum)
{
	if(flag)
	{
		return;
	}
	if(st.count(sum)&&to!=b)
	{
		flag=1;
		return;
	}
	for(auto &x:vec[to])
	{
		if(x.f==from)
			continue;
		dfs_b(to,x.f,sum^x.w);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		st.clear();
		for(int i=1;i<=n;i++)
		{
			vec[i].clear();
		}
		cin>>n>>a>>b;
		int u,v;
		ll w;
		for(int i=1;i<n;i++)
		{
			cin>>u>>v>>w;
			vec[u].push_back({v,w});
			vec[v].push_back({u,w});
		}
		flag=0;
		dfs_a(0,a,0);
		dfs_b(0,b,0);
		if(flag)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;	
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值