[CodeForces - 1041D]
中文意
你现在处于高度为h的地方,每秒y坐标会减少1,x坐标会增加1,而现在会有n个气流区[l,r],在每个气流区中,你的y坐标不会改变,你的x坐标每秒会增加1。(保证所给出的气流两两之间没有交集)现在你可以从x轴上的任意一点下落,现在问你最远的飞行路径。(即终点x坐标 减 起点x坐标的最6大值)
题目摘自:https://blog.csdn.net/qq_41289920/article/details/82962809
思路
一开始想到的是用一颗线段树维护区间最大值(区间-1最小),一棵树维护区间长度。但一般超过10^5以上的长度便不可使用线段树。
数据在10^5左右,猜测是nlogn算法。
这里提升一下思维。要有区间化点的思想,而差分就可以实现这个思想。同时差分可以用o(1)的时间算出区间M~N的值。处理差分的时间为o(n)。另:差分不支持修改,所以引出了树状数组概念。所以不修改区间的,用差分,修改区间的用树状数组
代码
#include<bits/stdc++.h>
using namespace std;
const int MAX = 2e5 + 5;
int n,h;
int b[MAX],c[MAX];
struct Node {
int l,r;
} node[MAX];
int main()
{
cin>>n>>h;
for(int i = 1; i<=n; i++) scanf("%d%d",&node[i].l,&node[i].r);
c[1] = 0;b[1] = node[1].r-node[1].l;
///因为飞机优先从气流区开始飞行,前缀区间可视作0
for(int i = 2; i<=n; i++) {
b[i] = node[i].r - node[i].l;
c[i] = node[i].l - node[i-1].r;
b[i] += b[i-1];
c[i] += c[i-1];
}
c[n+1] = INT_MAX;//这句貌似可以没有、、
int maxx = -1,ans;
for(int i = 1; i<=n; i++) {
int pos = lower_bound(c+1,c+n+1,c[i]+h) - c;///lower_bound复杂度为logn
ans = b[pos-1] - b[i-1];
maxx = max(maxx,ans);
}
printf("%d\n",maxx+h);
return 0 ;
}