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;
}