codeforces round 974(div.3) D(学会灵活拆分数据)
解题历程:
首先想到的是用数组记录,遍历每一个任务的区间,对区间内的数值加1,比如对于发生在4和8天之内的任务,a[4]++,a[5]++……a[8]++。然后用双指针,记录持续天数的开始下标和结束下标,以l和l+d为边界的窗口遍历每一天,若是最高位寻找任务最多的一天,和区间最大值最小的一天。
后来发现题目要求的是任务的种类最多和最小而不是某一天数量最多,所以之前的思考全部都是错的。
之后我仔细观察窗口在滑动的时候发现当遇到任务的开始的那天时,窗口内的任务数会增加,当人任务的结束的那天离开窗口时,窗口内的任务数会减少,在这个现象中,任务的开始只与窗口的右边有关,任务的结束只与窗口的左边有关,那么就可以将任务的开始与结束拆开分别存储然后分别排序,然后用两个变量分别存储最大值和最小值这样就能找到答案了
代码:
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define endl "\n"
#define inf 1e9
using namespace std;
int main(void )
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int test;
cin>>test;
while(test--){
int n,k;
int mins=inf,maxs=0;
cin>>n;
vector<int>a(n+1,0);
vector<int>r,l;
int d;
cin>>d>>k;
while(k--)
{
int t;
cin>>t;
l.push_back(t);
cin>>t;
r.push_back(t);
}
l.push_back(1);
r.push_back(n);
sort(all(r));
sort(all(l));
int l1=1,r1=d;
int ans1=1,ans2=1;
int t=0;
int t1,t2;
t1=0,t2=0;
while(l[t1]<=r1){
t++;
t1++;
}
maxs=t;
mins=t;
for(int i=0;i+r1<=n;i++){
while(t2<r.size()&&r[t2]<l1+i){
t--;
t2++;
}
while(t1<l.size()&&l[t1]<=r1+i){
t++;
t1++;
}
if(mins<t){
mins=t;
ans2=l1+i;
}
if(maxs>t){
maxs=t;
ans1=l1+i;
}
}
cout<<ans2<<' '<<ans1<<endl;
}
return 0;
}
反思:
看完题目的第一步不应该是直接套公式解题,要做的应该是分析数据,观察数据的变化和特点,观察数据之间的联系