问题描述
最近西西艾弗岛上出入各个场所都要持有一定时限内的核酸检测阴性证明。
具体来时,如果在 t 时刻做了核酸检测,则经过一段时间后可以得到核酸检测阴性证明。这里我们假定等待核酸检测结果需要 k 个单位时间,即在 t+k 时刻可以获得结果。如果一个场所要求持 24 个单位时间内核酸检测结果入内,那么凭上述的核酸检测结果,可以在第t+k 时刻到第 t+k+23 时刻进入该场所。
样例输入
6 2 10
5 24
10 24
11 24
34 24
35 24
35 48
1
2
样例输出
3
3
这道题是真的老六,我真的服了它了。
下面给出正确代码及一些感悟。
首先,之前看CSDN的时候,有个大佬说的好,这道题:
70分代码的思路我们是站在人的角度处理问题,即按照他的思路(即题目要求)一步一步处理问题,优先解决人的需求;
100分代码思路中,我们优先处理场所需求,即判断出进入该场所需要的最早时间核酸报告(left)
和最晚时间核酸报告(right)后考虑人的需求,即人在left~right这个时间范围内进入场所都是符合要求的,可将问题转化为对区间的处理:核酸检测的时间t+等待核酸检测的时间k所在的点有多少个满足条件的场所
也就是说,转换视角是十分重要的,而这一点是比较好想的。
这道题老六在哪里呢。
数据的范围!
这里要注意,是没有qm<tn的条件的,
换句话说,有可能我查询的是所有出行都结束之后毫无意义的时间
哪怕这种情况毫无意义,但你必须考虑到,否则就是错误!
而这个(qn+tn)能大到多少呢,3*10^5。
考虑到了嘛?
无语了。
下面给出代码(人比较菜,用了最容易理解的方法,没用差分数组)
70分代码,很简洁
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k;
cin>>n>>m>>k;
int t[n],c[n];
for (int i=0;i<n;i++)
{
cin>>t[i]>>c[i];
}
for (int i=0;i<m;i++)
{
int now;
int count=0;
cin>>now;
for (int j=0;j<n;j++)
if ((t[j]-c[j]+1<=now+k) && now+k<=t[j]) count++;
cout<<count<<endl;
}
return 0;
}
100分代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k;
cin>>n>>m>>k;
int t[n],c[n];
int maxt=0;
for (int i=0;i<n;i++)
{
cin>>t[i]>>c[i];
maxt=max(t[i],maxt);
}
const int maxnum=300000;
//测试数据中有qm>tm的数据(qm范围到200000,写到200000可得70分)
//还需要考虑到qm+k有可能最大到达300000,写到300000可得100分
int count[maxnum+1];
for (int i=0;i<=maxnum;i++) count[i]=0;
for (int i=0;i<n;i++)
{
for (int j=max(0,t[i]-c[i]+1);j<=t[i];j++) count[j]++;
}
// for (int i=0;i<=maxt;i++) cout<<count[i]<<" ";
// cout<<endl;
for (int i=0;i<m;i++)
{
int temp;
cin>>temp;
cout<<count[temp+k]<<endl;
}
return 0;
}