被老师布置作业的我(蒟蒻)无助地翻开题解,只见大佬们又是template又是namespace的,看得我一脸懵,被迫学习了一篇CSDN的题解,现说一说些微的体会来加深自己的印象
本文灵感来自于CSDN @jerome_wei
·
首先环上的问题我们一般改成链来做,其主要方法是输入完数据后再复制一遍加到原数组后面

(背景颜色#66CCFF)
另外我们使用struct定义每个士兵的编号以及奔袭区间
cpp
struct soldier {
int id, l, r;
} s[400005];cpp
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> s[i].l >> s[i].r;
if(s[i].r < s[i].l)
s[i].r += m;
s[i].id = i;
}
sort(s + 1, s + 1 + n, cmp);
for(int i = 1; i <= n; i++) {//此处即复制过程
s[i + n] = s[i];
s[i + n].l = s[i].l + m;
s[i + n].r = s[i].r + m;
}关于上文中的sort
因为每个士兵的奔袭区间不会被完全包含,所以我们按照每位士兵的区间左端点由小到大排序,就可以得到单调递增的区间
·
接下来我们想要去寻找每个士兵能奔袭的最远的边防站使得最少的士兵需要奔袭
这句话可能比较难理解,我们使用样例做出解释

图比较糙……假如我们的战士从4到7,另一名战士从7到3,那么那名从6到1的战士就不必参加,因此我们想到可以枚举每个区间内的战士,但是这样的复杂度是不能接受的,我们需要更快的时间,因此——
倍增!
·
我们预处理每名战士
从一名战士开始,一直到某一名战士的左端点大于这名战士的右端点,那么这名战士区间内奔袭过的最远的战士找到了
我们设表示第 个战士奔袭 步到达的边防站(表达不是很清楚,请读者自行感受)
方程为
