未初始化警告
问题
给出若干条赋值语句的左右值的下标,判断哪些语句是没有初始化的。
思路
判断标准就是,右值的下标非0的时候,之前不曾在左侧出现。使用map,快速判断之前是否存在这个值。
使用一个map来记录左值的下标出现次数,每接收一对左、右值,当右值非常量且右值之前不在map中,结果加一,对于所有的都要左值加一。
#include <bits/stdc++.h>
using namespace std;
int main() {
map<int, int> Left;
int left, right;
int n, k;
cin >> n >> k;
int ans = 0;
for(int i = 0; i < k; i++) {
cin >> left >> right;
//非常量,且之前没出现过
if(right != 0 && Left[right] == 0) {
ans++;
}
Left[left]++;
}
cout << ans << endl;
return 0;
}
出行计划
问题
有n个出行计划,(t,c)数据对,表示要进入该场所的时刻和该场所要求的核酸有效期。t1 时刻做了核酸,k个单位时间拿到核算报告,对于(t0,c0)场所,
t1 + k <= t0, t0 - (t1 + k) < c0,即到达该场所时,报告已经生效,且此时生效的时间小于场所的要求有效时间。对于n个出行计划,有m个时刻做核酸的选择,核酸生效的时间是k,求m个q各自能满足多少个出行计划。
思路
其实也可以暴力的方法,对于每个q遍历每个场所,看能否满足要求。
也搜索了优秀的方法。我先试一下暴力的方法。不出所料地错误。
70分
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, m, k;
cin >> n >> m >> k;
vector<vector<int> > sch(n,vector<int>(2));
for(int i = 0; i < n; i++){
cin >> sch[i][0] >> sch[i][1];
}
int q;
int t;
int count;
for(int i = 0; i < m; i++){
cin >> q;
count = 0;
t = q + k;//报告生效时刻
for(int j = 0; j < n; j++){
if(sch[j][0] >= t && sch[j][0] <= t + sch[j][1] - 1){
count++;
}
}
cout << count << endl;
}
return 0;
}
50分
和70的区别在于没有存储结果,判断一个p输出一次,看来以后不用等到最后才输出,这样就能免去一次循环。
using namespace std;
int main(){
int n, m, k;
cin >> n >> m >> k;
vector<vector<int> > sch(n,vector<int>(2));
vector<int> ans(m,0);
for(int i = 0; i < n; i++){
cin >> sch[i][0] >> sch[i][1];
}
int q;
int t;
for(int i = 0; i < m; i++){
cin >> q;
t = q + k;//报告生效时刻
for(int j = 0; j < n; j++){
if(sch[j][0] >= t && sch[j][0] <= t + sch[j][1] - 1){
ans[i]++;
}
}
}
for(int i = 0; i < m; i++){
if(ans[i]) cout << ans[i] << endl;
}
return 0;
}
优秀的思路
搜索了各种,又是使用差分数组,意识到自己还是没学会差分数组和前缀和。看大家的题解也觉得没看懂,在b站找了视频,终于理解了。
202203(第25次)CCF CSP真题202203-1,2讲解
之前我们是以核算报告的角度考虑,看每个场所能否进入,这次换做从场所的角度考虑,看这个场所允许哪些时间的报告进入。然后使用差分数组将这些报告的时间对应的值都加一,再求前缀和得到每个时间点的得分,最后根据输入的查询,直接得到满足几个场所。
每个场所的允许进入的核酸报告的时间区间是**(t - c, t],最早是报告刚好没有超时(也就是进入时刻 t 往前推 c 个小时),最晚是报告刚好生效。
因为时间都是整数,所以区间可以改成[t - c - 1, t]**还要注意,区间的边界有效,右区间,肯定合法,但左区间
可能会小于0,所以要使规范,左区间最小为1。
借用视频的讲解图:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 4e5+10;
int main()
{
int n,m,k;
int b[N];//差分数组
cin >> n >> m >> k;
int t, c;
for(int i = 1; i <= n; i++)
{
cin >> t >> c;
int left = t - c + 1;//定义左边界
left = left > 0 ? left : 1;
int right = t;//定义右边界
//left ~ right之间的数都+1
b[left]++;
b[right+1]--;
}
//前缀和操作,得到各个点的数值
for(int i = 1; i <= N; i++){
b[i] = b[i-1] + b[i];
}
while(m--)
{
int x;
cin >> x;
cout << b[x+k] << endl;//直接得到x+k处的数值
}
return 0;
}
get
再次体验到差分数组和前缀和