这次的div3整体不难就是有些细节问题,有两道题因为细节问题gg了.
文章目录
一、A - Everyone Loves to Sleep
- 题目:
给你小明的睡觉时间,给你小明订的闹钟个数和每个闹钟的时间,闹钟响,小明就会起来,问你小明从睡觉到醒来用了多长时间 - 思路
直接"乱炖",把所有的时间都变成分钟,然后24小时是一个周期,就是当前的(闹钟时间 - 睡觉时间 + 24 * 60) % (60 * 24) - 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 1e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
int a[N];
void solve()
{
int n,h,m; cin >> n >> h >> m;
int k = h * 60 + m;
int t = INF;
for(int i = 1;i <= n;i ++ )
{
int a,b; cin >> a >> b;
int q = a * 60 + b;
int s = (q - k + 24 * 60) % (24 * 60);
t = min(t,s);
}
cout << t / 60 << ' ' << t % 60 << endl;
}
signed main()
{
ios;int T;cin >> T;
while(T -- ) solve();
return 0;
}
二、B - Remove Prefix
- 题目:
你每次可以删除开头的一个数字,问你几次可以把数组A变成没有重复数字的数组 - 思路:
因为是从开头删除的,所以直接从后面往前面算,如果 x 出现两次的话,那就直接记录此时的下标,输出就行 - 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 1e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
int a[N];
int b[N];
void solve()
{
int n; cin >> n;
memset(b,0,sizeof b);
for(int i = 1;i <= n;i ++ ) cin >> a[i];
int id = 0;
for(int i = n;i >= 1;i -- )
{
b[a[i]]++;
if(b[a[i]] >= 2)
{
id = i;
break;
}
}
cout << id << endl;
}
signed main()
{
ios;int T;cin >> T;
while(T -- ) solve();
return 0;
}
三、C - Minimum Varied Number
- 题目::
给你一个数字n,然后你需要找到一个最小的数字x,使得x的每一位相加之和是n,输出x - 思路:
因为想要x最小,所以贪心从9一直到1,也就是从低位9到高位1过渡 - 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 1e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
int a[N];
int b[N];
void solve()
{
int n; cin >> n;
string s;
vector<int>res;
int k = 9;
while(n != 0)
{
if(n >= k)
{
n -= k;
res.pb(k);
}
k--;
}
for(int i = res.size() - 1;i >= 0;i --) cout << res[i];
cout << endl;
}
signed main()
{
ios;int T;cin >> T;
while(T -- ) solve();
return 0;
}
四、D - Color with Occurrences
-
题目:
给你一个标准字符串T,给你n个匹配字符串S,如果S[i]是T的子串,就可以把T中与S[i]相同的字串染色,问你T被全部染色的最小次数是多少,每次选择的是哪一个S -
思路:
这个也是贪心,枚举每一个T[i],每次更新最大匹配长度,那如何计算次数,rmax为最大匹配长度,r为rmax更新之前的值,如果当前的i > r 代表此时依然没有染色完全,此时次数ans++, 如果当前 i == rmax,并且更新完成以后i == rmax,代表肯定失败,注意细节.代码写的有点不好,凑活看吧
-
代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 20,M = 1e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
vector<PII> res;
bool st[N];
void solve()
{
string t; cin >> t;
int n; cin >> n;
string s[N];
for(int i = 1;i <= n;i ++ ) cin >> s[i]; // 重复的越少越好并且越大越好
int ans = 0;
int r = 0,rmax = -1;
int g = 0;
res.clear();
int len = 0,x = 0;
for(int i = 0;i < t.size();i ++ ) // 看每一个字符最远能到多少
{
if(i > r)
{
ans++;
res.pb({len,x + 1});
r = rmax;
if(len == 0)break;
}
int p = 0;
for(int j = 1;j <= n;j ++ )
{
int f = 0;
int w = i;
for(int k = 0;k < s[j].size();k ++,w ++)
{
if(t[w] != s[j][k])
{
f = 1;break;
}
}
if(f == 0) // 匹配了 那我要最大的
{
if(w > rmax)
{
rmax = w;
x = i;
len = j;
}
if(w == t.size())
{
p = 1;
break;
}
}
}
if(p == 1)
{
g =1;
ans++;
res.pb({len,x + 1});
if(len == 0)g = 0;
break;
}
if(i == rmax)break; // 错误的
}
if(g)
{
cout << ans << endl;
for(int i = 0;i < res.size();i ++ )
cout << res[i].fi << ' ' << res[i].se << endl;
}
else cout << "-1" << endl;
}
signed main()
{
ios;int T;cin >> T;
while(T -- ) solve();
return 0;
}
五、E - Add Modulo 10
- 题目
- 给你一个数组A,每一次操作都可以使得A[i] = A[i] + (A[i] % 10),问你能否使得A中每一个元素都相等
- 思路:
因为个位数只有0到9,当A[i]的个位数为0时,所有的A[i]经过操作后都得是这个数字,这个有个规律,就是如果A[i] % 10 == 0 ,那A[i]不变,A[i] % 10 == 5,那A[i]最多变一次为A[i] + 5,其他数字经过几次变换最终个位数都是按照 2 4 8 6 的周期进行,也就是每一次都必须加 20 (2 + 4 + 8 + 6)所以我们可以把A[i] 都变成个位数字为2的A[i],然后所有的A[i]都必须符合 A[i] + k1 * 20 == A[j] + k2 * 20,化简就是每一个都要符合 (A[i] - A[j]) % 20 == 0,这里我们就让q = 最大的A[i],所以最后每一个A[i]都必须符合(q - A[i]) % 20 == 0 - 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 1e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
int a[N];
void solve()
{
int n; cin >> n;int d = 0;
int q = -1;
for(int i = 1;i <= n;i ++ ) cin >> a[i];
for(int i = 1;i <= n;i ++ )
{
if(a[i] % 10 == 5) a[i] += 5,d++;
else if(a[i] % 10 == 0) d++;
else
{
while(a[i] % 10 != 2)
{
a[i] = a[i] + (a[i] % 10);
}
q = max(q,a[i]);
}
}
int f = 0;
if(d == n)
{
for(int i = 2;i <= n;i ++ )
if(a[i] != a[1])
{
f = 1;break;
}
}
else if(d > 0) f = 1;
else
{
for(int i = 1;i <= n;i ++ )
{
if((q - a[i]) % 20 != 0)
{
f = 1; break;
}
}
}
cout << (f == 0? "Yes" : "No") << endl;
}
signed main()
{
ios;int T; cin >> T;
while(T -- ) solve();
return 0;
}
六、F - Build a Tree and That Is It
- 题目:
无根树,n个点,给你D(1,2),D(2,3),D(3,1)的距离,问你是否能构造出这个树 - 思路:
这个思路很好想,就是代码写的细节很多,我们先以 1为根节点,先固定2的点(固定3的点也一样) 第一种情况在代码中写出来了,这里分析第二种情况,代码写的风格不是很节俭
- 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 4e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
vector<PII> res;
void solve()
{
int n,d12,d23,d31; cin >> n >> d12 >> d23 >> d31;
res.clear();
if(d12 == d23 + d31) // 一条链子上面并且 2在最下面 3在中间
{
cout << "YES" << endl;
int k = 1,s = 4,d = 1;
while(d <= d12)
{
if(d == d31)
{
res.pb({k,3});
k = 3;
d++;
continue;
}
if(d == d12)
{
res.pb({k,2});
break;
}
else
{
res.pb({k,s});
k = s;
s++;
}
d++;
}
for(int i = s;i <= n;i ++ )
{
cout << 1 << ' ' << i << endl;
}
for(auto x:res)
cout << x.fi << ' ' << x.se << endl;
}
else
{
if((d12 + d31 - d23) % 2 != 0) cout << "NO" << endl;
else
{
int p = (d12 + d31 - d23) / 2; // 在p这个点分开
if(p + d23 + 1 > n || p < 0 || p > d12 || p > d31) cout << "NO" << endl;
else
{
cout << "YES" << endl;
int k = 1,s = 4,d = 1,u;
while(d <= d12)
{
if(d == p)
{
u = s;
}
if(d == d12)
{
res.pb({k,2});
}
else
{
res.pb({k,s});
k = s;
s++;
}
d++;
}
if(p == 0)
k = 1,d = 1;
else if(p == d12)
k = 2,d = p + 1;
else
k = u,d = p + 1;
while(d <= d31)
{
if(d == d31)
{
res.pb({k,3});
}
else
{
res.pb({k,s});
k = s;
s++;
}
d++;
}
for(int i = s;i <= n;i ++ ) cout << 1 << ' ' << i << endl;
for(auto x:res)
cout << x.fi << ' ' << x.se << endl;
}
}
}
}
signed main()
{
ios;int T; cin >> T;
while(T -- ) solve();
return 0;
}
七、G - Path Prefixes
- 题目:
给你n个点,1为根节点 然后给你边,每条边都有两个权值A[i],B[i],从1开始到点 u 路径中的所有边的A[i]之和 >= 从1开始到点 v 路径中的所有边的B[i]之和(v是1到u路径中的某个点,同时这个v点的深度尽可能的大) 求出每一个点u对应v的最大深度 - 思路:
树上前缀和 dfs , bfs 都行,然后寻找点v的话,就是利用倍增思想,快速找到符合条件的v点,或者用二分求也行,我用的是bfs - 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,M = 4e5 + 100,mod = 1e9 + 7,INF = 0x3f3f3f3f;
int h[N],e[N],a[N],b[N],ne[N],idx;
int sa[N],sb[N];
int res[N];
int fa[N][20];
int d[N];
void add(int u,int v,int w1,int w2)
{
e[idx] = v,a[idx] = w1,b[idx] = w2,ne[idx] = h[u],h[u] = idx ++ ;
}
int check(int x,int val) // 2 16
{
for(int i = 19;i >= 0;i -- )
{
if(sb[fa[x][i]] >= val)
x = fa[x][i];
}
if(sb[x] <= val) return d[x];
else
return d[fa[x][0]];
}
void bfs()
{
queue<int> q; q.push(1); d[1] = 0;
while(q.size())
{
int t = q.front();q.pop();
res[t] = check(t,sa[t]);
for(int i = h[t];i != -1;i = ne[i])
{
int j = e[i];
q.push(j);
sa[j] = sa[t] + a[i];
sb[j] = sb[t] + b[i];
fa[j][0] = t;
d[j] = d[t] + 1;
for(int k = 1;k <= 19;k ++ )
fa[j][k] = fa[fa[j][k - 1]][k - 1];
}
}
}
void solve()
{
int n; cin >> n;
memset(h,-1,sizeof h);idx = 0;
for(int i = 2;i <= n;i ++ )
{
int u,ai,bi; cin >> u >> ai >> bi;
add(u,i,ai,bi);
sa[i] = 0,sb[i] = 0,res[i] = 0,d[i] = 0;
}
bfs();
for(int i = 2;i <= n;i ++ ) cout << res[i] << ' ';
cout << endl;
}
signed main()
{
ios;int T; cin >> T;
while(T -- ) solve();
return 0;
}