题目传送门
可以看到题目给出的
L
i
L_i
Li和
R
i
R_i
Ri其实规定的是当
l
l
l小于等于
L
i
L_i
Li时
r
r
r必须小于
R
i
R_i
Ri。因此我们只要求出
i
i
i为
l
l
l时最大的
r
r
r,然后把他们的区间的数字数量加起来,可是这样的时间复杂度接近
O
(
n
m
)
O(nm)
O(nm),能不能再优化呢?当然可以,既然是小于等与
L
i
L_i
Li的数都被限制,那么为什么不可以设
a
i
a_i
ai为当
l
l
l小于等于
i
i
i时
r
r
r的最大取值呢:在每次输入
L
i
L_i
Li和
R
i
R_i
Ri时设置
a
L
i
=
m
i
n
(
a
i
,
R
i
−
1
)
a_{L_i}=min(a_i,R_i-1)
aLi=min(ai,Ri−1),然后从后往前遍历每一个数让
a
n
s
ans
ans加上
i
i
i和它最大右端点的取值就可以了(如果从前往后的话会出现
a
a
a数组后面的元素小于前面的元素的情况,而从后往前我们只需要忽略掉前面比他大的元素就可以了)。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,s,ans,a[500005];
//a[i]为当l小于等于i时r的最大取值
main(){
cin>>m>>n;
memset(a,-1,sizeof a);
a[n]=n;
while(m--){
int l,r;
cin>>l>>r;
if(a[l]==-1){
//直接赋值
a[l]=r-1;
}else{
//找到最小的r的最大取值
a[l]=min(r-1,a[l]);
}
}
//s是当前的最大r的最大取值
s=a[n];
for(int i=n;i>=1;i--){
//当前面的r的最大取值比当前的苛刻就更新s
if(s>a[i]&&a[i]!=-1){
s=a[i];
}
//ans加上从l到r一共可选的总数
ans+=(s-i+1);
}
cout<<ans;
return 0;
}