Codeforces Round #787 (Div. 3)

A. Food for Animals

在这里插入图片描述

Sample input

7
1 1 4 2 3
0 0 0 0 0
5 5 0 4 6
1 1 1 1 1
50000000 50000000 100000000 100000000 100000000
0 0 0 100000000 100000000
1 3 2 2 5

Sample ouput

YES
YES
NO
YES
YES
NO
NO

题意:

x只狗,y只猫,a袋狗粮,b袋猫粮,c袋万能粮,问你能不能满足所有的猫和狗都吃上饭

思路:

就是简单的贪心,直接上代码把

#include<bits/stdc++.h>
using namespace std;

void solve(){
	int a,b,c,x,y;
	cin>>a>>b>>c>>x>>y;
	if(a < x) c -= x-a;
	if(b < y) c -= y-b;
	if(c < 0) puts("NO");
	else puts("YES");
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
} 

B - Make It Increasing

在这里插入图片描述

Sample input

7
3
3 6 5
4
5 3 2 1
5
1 2 3 4 5
1
1000000000
4
2 8 7 5
5
8 26 5 21 10
2
5 14

Sample output

2
-1
0
0
4
11
0

题意:

给你一个长度为n的数组,你每进行一次操作就会选定一个位置的元素,让他除以二下取整,问你最少需要多少次操作才能使得这个数组变成严格递增的数组,如果不能变成的话输出-1

思路:

就是从高位元素到低位元素遍历,如果比后面的数大就除以二,最后判断一下是否前两个数都为0就行,下面看代码把

#include<bits/stdc++.h>
using namespace std;

void solve(){
	int a[40],n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	int ans = 0;
	for(int i=n-1;i>=1;i--){
		while(a[i] && a[i] >= a[i+1]){
			a[i] /= 2;
			ans++;
		}
	}
	if(n == 1) puts("0");
	else{
		if(a[1] == a[2]) puts("-1");
		else printf("%d\n",ans);
	}
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
} 

C. Detective Task

在这里插入图片描述

Sample input

8
0
1
1110000
???
1?1??0?0
0?0???
??11
??0??

Sample output

1
1
2
5
4
1
1
3

题意:

给你一个长度为n的字符串,每个字母的取值都为0,1,?,0代表当前这个人去屋子里没有看见宝物,1嗲表这个人去屋子里看见了宝物,?代表这个人忘了,这n个人中只有一个小偷,小偷可以说0,1,?其中的任意一个,但是其他人说的都是实话, 问可能成为小偷的人有多少个

思路:

有这么一个思路,就是枚举每一个人是小偷,那么他前面的都为1,后面的都为0,?可以省略,然后就可以想到找最后一个1和第一个0,然后他中间的都可能是小偷,下面请看代码

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
char s[N];
void solve(){
	scanf("%s",s+1);
	int n = strlen(s+1);
	int l = 1,r = n;
	for(int i=1;i<=n;i++) if(s[i] == '1') l = i;
	for(int i=n;i>=1;i--) if(s[i] == '0') r = i;
	printf("%d\n",r-l+1);
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
} 

D. Vertical Paths

在这里插入图片描述

Sample input

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

Sample output

3
3
3 1 5
1
2
1
4

2
2
1 2
2
4 3

1
7
1 2 3 4 5 6 7

1
1
1

3
3
4 1 5
2
2 6
1
3

3
2
2 1
1
3
1
4

题意:

给一个树,路径只能由父节点到子节点,把这棵树分为若干条路径,输出最小的路径数,并且输出每条路径长度和路径本身

思路:

最小路径数就是叶节点的数量,做法就是从每个叶节点开搜,然后如果搜到已经搜过的节点就停手,记录答案,不要忘了特判n=1的情况,下面请看代码

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
vector<vector<int> > ans;
int fa[N];
bool st[N];
vector<int> res;
void dfs(int u){
	if(st[u]){
		reverse(res.begin(),res.end());
		ans.push_back(res);
		return;
	}
	st[u] = true;
	res.push_back(u);
	dfs(fa[u]);
}
void solve(){
	int n;
	scanf("%d",&n);
	ans.clear();
	for(int i=1;i<=n;i++) st[i] = false;
	for(int i=1;i<=n;i++){
		scanf("%d",&fa[i]);
		st[fa[i]] = true;
	}
	queue<int> q;
	for(int i=1;i<=n;i++){
		if(!st[i]) q.push(i);
		st[i] = false;
	}
	while(!q.empty()){
		int t = q.front();
		q.pop();
		res.clear();
		dfs(t);
	}
	if(n == 1){
		puts("1\n1\n1\n");
		return;
	}
	printf("%d\n",ans.size());
	for(auto t : ans){
		printf("%d\n",t.size());
		for(auto x : t) printf("%d ",x);
		puts("");
	}
	puts("");
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
} 

E. Replace With the Previous, Minimize

在这里插入图片描述

Sample input

4
3 2
cba
4 5
fgde
7 5
gndcafb
4 19
ekyv

Sample output

aaa
agaa
bnbbabb
aapp

题意:

给定一个小写字母序列,和操作数,每次操作都可以把序列中每个字母变成前一位,输出操作后字典序最小的序列

思路:

就是暴力从前往后找,记录一个数re,表示能变成a的最大范围,如果k还够的话就继续往后找,如果不够的话就最后找一个能变成的区间,在这个区间里面的都变成最小字母,下面看代码把

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
char s[N];
void solve(){
	int n,k;
	scanf("%d%d%s",&n,&k,s+1);
	int re = 0;
	for(int i=1;k && i<=n;i++){
		if(s[i]-'a' > re){
			if(k >= s[i]-'a'-re){
				k -= s[i] - 'a' - re;
				re = s[i] - 'a';
			}
			else{
				char c = s[i]-k,c1 = s[i];
				for(int j=1;j<=n;j++){
					if(s[j]-'a' > c - 'a' && s[j] <= c1) s[j] = c;
				}
				break;
			}
		}
	}
	for(int i=1;i<=n;i++) if(s[i] - 'a' <= re) s[i] = 'a';
	puts(s+1);
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
} 

F. Vlad and Unfinished Business

在这里插入图片描述

Sample input

3

3 1
1 3
2
1 3
1 2

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

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

Sample output

3
7
2

题意:

给一棵树,有起点和终点,还有若干任务点。你要从起点出发,到达所有的任务点(不限顺序),然后最后到达终点,求最小步数

思路:

这个题跟今年的天梯赛L2-3非常像,这个题的做法是这样的,我先找到x和y之间的路径,然后分别以这条路径上的每个点为根来进行dfs,来求出每个点的father,然后做法跟第三题是类似的,这次是对于每个必须经过点进行一遍向上搜索,如果遇到了已经搜过的点就答案加2*len,len是以这个必须经过的点为起点搜到不能搜的长度,然后最后答案再加上x和y之间的路径长度就行了,具体看代码

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
vector<int> e[N],lu;
bool st[N],flag;
int ans = 0;
void dfs1(int u,int end,int fa){
	if(flag) return;
	if(u == end){
		for(auto t : lu) st[t] = true;
		ans = lu.size() - 1;
		flag = true;
		return;
	}
	for(auto v : e[u]){
		if(v == fa) continue;
		lu.emplace_back(v);
		dfs1(v,end,u);
		if(flag) return;
		lu.pop_back();
	}
}
int fa[N];
void dfs2(int u,int f){
	for(auto v : e[u]){
		if(v == f || st[v]) continue;
		fa[v] = u;
		dfs2(v,u);
	}
}
void dfs(int u,int cnt){
	if(st[u]){
		ans += cnt*2;
	}
	else{
		st[u] = true;
		dfs(fa[u],cnt+1);
	}
}
void solve(){
	int n,k,sta,end;
	vector<int> p;
	lu.clear();
	flag = false;
	scanf("%d%d%d%d",&n,&k,&sta,&end);
	for(int i=1;i<=n;i++) e[i].clear(),st[i] = false;
	for(int i=1;i<=k;i++){
		int t;
		scanf("%d",&t);
		p.emplace_back(t); 
	}
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].emplace_back(v);
		e[v].emplace_back(u);
	}
	lu.emplace_back(sta);
	dfs1(sta,end,-1);
	for(auto t : lu) dfs2(t,-1);
	for(auto t : p){
		dfs(t,0);
	}
	printf("%d\n",ans);
}
int main(){
	int _;
	for(cin>>_;_;_--) solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值