这道题题意就是你有k个工作,每个工作都有一个时间区间左边界l和右边界r,妈妈和哥哥要来看你,时长为d,题目要求求出 1.哥哥看你的这段时间工作时间段重叠最多是多少?2.妈妈看你的这段时间工作时间段重叠最少是多少?
这道题如果硬做的话可能就是线段树了(蒟蒻暂时没有想到其他的做法),但如果反正来想,不找重叠最多,而是找不重叠最少,不找重叠最少,而是找不重叠最多,这样就简单多了(大概...) 具体来说就是在来看你的这段时间d,如果重叠的工作最多,那么在这段时间的“两边”的“独立”的工作最少,反之如果重叠的工作最少,那么在这段时间的“两边”的“独立”的工作最多。除此之外,这道题还有一个非常有趣的点是对于工作时间的处理,将原本的区间形状的时间变化为点状的时间(大家可以体会一下,我不太会描述,这点我当时比较困惑,琢磨了一段时间),这样更方便进行操作,非常非常的精妙。下面放代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;void slove(){ll n, d, k;cin >> n >> d >> k;vector <ll> a(n + 1, 0), b(n + 1, 0);for(ll i = 1; i <= k; i ++){ll l, r;cin >> l >> r;l --;a[l] ++, b[r] ++;}//右边界for(ll i = 1; i <= n; i ++){b[i] += b[i - 1];}//左边界for(ll i = n - 1; i >= 0; i --){a[i] += a[i + 1];}ll mx = -1, mn = n + 1, idmx, idmn;n -= d;for(ll i = 0; i <= n; i ++){ll num = b[i] + a[i + d];// cout << num << endl;if(num > mx){mx = num;idmx = i + 1;}if(num < mn){mn = num;idmn = i + 1;}}// cout << "ans:";cout << idmn << " " << idmx << endl;return ;
}
int main(){ll t;cin >> t;while(t --){slove();}return 0;
}
对于这道题我起初的思路是用树状数组来维护,但处理的时候时间复杂度会出问题,又想到了线段树,但写起来麻烦,就没有继续进行,一直没想到什么巧妙的想法,直到看了哥哥的视频,起初也没看懂,后来恍然大悟,琢磨半天终于懂了,哥哥吴迪啊啊啊!!!
最近太摆,前几天本来说写这道题题解的,一直拖延再加上玩,就拖到了今天...好好调整吧,争取在国庆集训回归正轨