5.6CF做题日记【Codeforces Round #787 (Div. 3)A~D】(虚拟场补题)
前言
前三个一小时做出来了,但是后面出去没做了,后来d也是自己做的,加油
题目链接集合
Dashboard - Codeforces Round #787 (Div. 3) - Codeforces
A. Food for Animals
题意
给出 a b c x y,分别指给狗的食物数量,给猫的食物数量,给猫和狗都能吃的食物数量,狗应吃食物数量,猫应吃食物数量; 求猫和狗是否够吃
分析
题不难, 但也容易出乱子,这里我用的是看猫和狗需要在c食物里拿多少,然后和c比较
代码
#include<iostream> using namespace std; int main(){ int a,b,c,x,y,n=0,t,j=0; cin>>t; while(t--) { cin>>a>>b>>c>>x>>y; if(a<x) n=x-a;//狗额外需要的 if(b<y) j=y-b;//猫额外需要的食物 if((n+j)<=c) cout<<"YES\n"; else cout<<"NO\n"; n=0,j=0; } }
B. Make It Increasing
题意
每次可以把一个数除2,下取整,问需要操作多少次才能使序列递增(相邻两数可以相等)
分析
从后往前遍历,如果大于后面的数字,就一直除,但是,如果前面尽量小的话,那最后的序列应该是0 1 2 3 4 5 6...... 也就是说满足a[i]>=i-1 (i=1~n-1)
需要注意的是考虑除到0不能再除了,要不然会一直循环(超时警告)
AC代码
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int N = 1e5+10; int a[50]; int main() { int t; scanf("%d", &t); while(t --) { int n; cin >> n; for(int i = 1; i <=n ;i ++) cin >> a[i]; bool f = 1; int times = 0; if(a[n]==0 && n!=1)f = 0; else for(int i= n-1; i >= 1; i --) { while(a[i]>=a[i+1]) a[i]/=2, times++; if(a[i]<i-1) { f=0; break; } } if(!f)cout << "-1\n"; else cout << times<<endl; } return 0; }
C. Detective Task
Problem - C - Codeforces 类型:模拟
题意
画被偷走了,一共有一些人来依次看过画,主人问他们你们来的时候画还有没有,只有拿画人可以撒谎,求有几个人是嫌疑人
每个人只有3种回答:
1:来的时候画还在
0:来的时候画不在
?:记不清了
数据范围
t [1,1e4] s长度总和不大于2e5
分析
有几种情况:(代码中有详解)
全是0和?:那就第一个0和前面的问号是嫌疑人
全是1和?:那就最后一个1和后面的问号是嫌疑人
0和1都有出现:那就0和1之间是嫌疑人(包括0和1)
AC代码
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int N = 1e5+10; int a[50]; int main() { int t; scanf("%d", &t); while(t --) { string s; cin >> s; int sum = 0, tem = 0, num1 = 0; bool f0 = 0, f1 = 0;//f0是说有没有0出现, f1同理 for(int i = s.size()-1; i >= 0; i --) { if(f0 && f1)break; if(s[i]=='?') tem ++; if(s[i]=='1') f1=1, sum = tem;//把结果传给sum else if(s[i]=='0') f0=1, tem=1;//开始计数 if(!f1) num1++; } if(f0 && f1) cout << sum+1<<endl; //正常0和1之间的个数(包括0 1) else if(f0) cout << tem<<endl; //0和前面的?的集合 else if(f1) cout << num1+1 <<endl; //1和后面?的集合 else cout << s.size()<<endl;//全程都是‘?’ } return 0; }
来了来了, 最有练代码的题来了
D. Vertical Paths
Problem - D - Codeforces 类型:树,dfs
题意
给出一个树,要把数划分成尽量少的路,每一段路不能重复,输出路的数量,以及每条路走过的点
分析
大致思路:其实代码是类似于链表的,但是是用vector和queue存的,然后一步步的dfs,但是有些东西还是要注意的(超时警告)
1. 不能有重复的路,每次的路清空,不要再留在队里了
2. 超内存的问题,开始开了俩vector套queue,其中一个作为输出,一个是存子节点,后来是把存输出的给直接输出了,但是要提前知道有多少条路
每个父节点,都不用单独开一条路,下面的子节点如果要开路会带着他们,所以路的条数 = n - 父节点个数
AC代码
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int N = 2e5+10; int n, q[N], idx=0, coun=0; queue<int> v[N]; void dfs(int root, int q[]) { if(v[root].size()==0)//输出 { cout <<idx<<endl; for(int i = 0; i < idx; i ++) cout << q[i]<< ' '; cout<<endl; idx=0; return; } while(v[root].size()) { int t = v[root].front(); v[root].pop(); q[idx++]=t; dfs(t,q); idx=0;//走过就清空 } } void init() { for(int i = 0; i<= n;i++) while(v[i].size()) v[i].pop(); idx=0; coun =0; } int main() { int t; scanf("%d", &t); while(t --) { init(); int root, x; cin >> n ; for(int i = 1; i <= n; i ++) { cin >> x; if(x!=i) { v[x].push(i); if(v[x].size()==0)//因为当x==i,v[x]里并不会加元素,还是空 coun ++; } else root = i; } q[0]=root; idx=1; cout << n-coun <<endl; dfs(root,q); cout <<'\n'; } return 0; }