A. Everyone Loves to Sleep
题意:
给定一天中某个时刻,给定若干数量的闹钟,询问时刻到最近闹钟的时间
解析:
遍历做差即可,输出最小值
代码:
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 15;
const int INF = 0x3f3f3f3f;
struct alerm{
int h, m;
int t;
}a[maxn];
int n, H, M;
void solve(){
cin >> n >> H >> M;
int t = H*60+M;
int ans = INF;
for(int i = 1; i <= n; i++){
cin >> a[i].h >> a[i].m;
a[i].t = a[i].h*60+a[i].m;
}
for(int i = 1; i <= n; i++){
int res = a[i].t - t;
if(res < 0)
res += 24*60;
ans = min(res, ans);
}
//cout << "ans = " << ans/60 << " " << ans%60 << endl;
cout << ans/60 << " " << ans%60 << endl;
return;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}
B. Remove Prefix
题意:
给定一个序列,移除开头几个数,使序列中的数各不相同。
解析:
从后向前遍历,找到第一个重复的位置。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
const int INF = 0x3f3f3f3f;
int a[maxn], cnt[maxn];
int n ;
void solve(){
memset(cnt, 0, sizeof(cnt));
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
int res = 0;
for(int i = n; i >= 1; i--){
int x = a[i];
if(cnt[x] == 0)
cnt[x]++;
else{
res = i;
break;
}
}
//cout << "ans = " << res << endl;
cout << res << endl;
return;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}
C. Minimum Varied Number
题意:
给定n,找到最小的数满足数位和为n且每个数位各不相同
解析:
从9到1遍历,能填则填
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> a;
int n;
void solve(){
a.clear();
cin >> n;
for(int i = 9; i >= 1; i--){
if(n >= i){
a.push_back(i);
n-= i;
}
}
for(int i = a.size()-1; i >= 0; i--)
cout << a[i];
cout << endl;
return;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}
D. Color with Occurrences
题意:
给定一个串t,和一些串s,如果s是t的子串,将t中对应位置涂红,询问最少的次数并输出方案
解析:
从前往后匹配t,每次选择使红色增加最多的s串
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 15;
struct res{
int idx, pos;
};
vector<res> ans;
string s[maxn];
string t;
int n, cur, lent;
int check(){
int len = 0, tmp = 0;
int pos = 0, idx = 0;
string tmpt;
for(int i = 1; i <= n; i++){
int lens = s[i].length();
tmp = 0;
for(int j = max(0, cur-lens); j+lens <= lent; j++){
if(j > cur)
break;
tmpt.erase(0, tmpt.length());
tmpt = t.substr(j, lens);
//cout << tmpt << endl;
if(tmpt == s[i])
tmp = lens - (cur-j);
if(tmp > len){
len = tmp;
idx = i;
pos = j+1;
}
}
}
if(len > 0){
ans.push_back({idx, pos});
cur += len;
return 1;
}
else
return 0;
}
void solve(){
ans.clear();
cin >> t;
lent = t.length();
cin >> n;
for(int i = 1; i<= n; i++)
cin >> s[i];
cur = 0;//当前未涂
int num = 0;
while(cur < lent) {
num++;
if(num > 100)
break;
if(check() == 0)
break;
}
if(cur >= lent){
cout << ans.size() << endl;
for(int i = 0; i < ans.size(); i++){
cout << ans[i].idx << " " << ans[i].pos << endl;
}
}
else
cout << -1 << endl;
return;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}
E. Add Modulo 10
题意:
给定长度为n的序列,对序列中的数x,可以x = x + x % 10。询问所有的数能不能变为相同的
解析:
随便找几个数,发现除了第一次加法,之后都是加2 4 8 6 循环,每个周期加20。所以对20取余,然后模拟加到40即可。
特判一下存在尾数为0、5的情况
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int a[maxn], b[maxn], n;
int cnt[100];
void f(int x){
int res = x;
while(x <= 40){
cnt[x]++;
x += x%10;
}
}
void solve(){
memset(cnt, 0, sizeof(cnt));
cin >> n;
int flag = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
a[i] = a[i]+a[i]%10;
if(a[i]%10 == 5 || a[i]%10 == 0){
flag = 1;
}
}
if(flag){
int x = a[1];
for(int i = 2; i <= n; i++){
if(a[i] != x){
cout << "no" << endl;
return;
}
}
cout << "yes" << endl;
return;
}
for(int i = 1; i <= n; i++){
a[i] = a[i]%20;
f(a[i]);
}
int vis = 0;
for(int i = 1; i <= 40; i++){
if(cnt[i] == n){
cout << "yes" << endl;
return;
}
}
cout << "no" << endl;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}
G. Path Prefixes
题意:
给定一棵n节点的树,边有两个边权a,b。对根节点意外的每个节点询问,到该节点路径上前面做多b的个数,满足b的和小于等于到该节点路径上a的和
解析:
dfs,记录到每个节点的a的和,以及路径上b的前缀和,二分查找即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int head[maxn], tot;
struct edge{
int to, nxt;
ll a, b;
}e[maxn << 1];
void add(int u, int v, ll a, ll b){
e[++tot].nxt = head[u];
e[tot].to = v;
e[tot].a = a;
e[tot].b = b;
head[u] = tot;
}
ll n, r[maxn];
void dfs(int u, int fa, vector<ll> &b, ll a){
if(u != 1)
r[u] = upper_bound(b.begin(), b.end(), a) - b.begin() -1;
ll tmp = b.back();
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fa)
continue;
b.push_back(tmp+e[i].b);
dfs(v, u, b, a+e[i].a);
b.pop_back();
}
}
vector<ll> b;
void solve(){
cin >> n;
memset(head, 0, sizeof(head));
tot = 0;
for(int i = 2; i <= n; i++){
ll p, a, b;
cin >> p >> a >> b;
add(i, p, a, b);
add(p, i, a, b);
}
b.clear(); b.push_back(0);
dfs(1, 0, b, 0);
for(int i = 2; i <= n; i++)
cout << r[i] << " ";
cout << endl;
return;
}
int main(){
int T;
cin >> T;
while(T--)
solve();
return 0;
}