【lgj】【分治】【小清新】【单调性】
因为要求一段区间。所以对于一个点 ,是否能被加入某段区间,设出边点集为 ,则只和 有关。
这样用区间搞一遍是 。
对于某些区间计数问题,考虑分治。假设我们要求 区间的答案,分成 ,求横跨两段的区间个数。
将两段分别探讨。
对于 区间中的 ,。这是可以扫一遍得到的,预处理出哪些 是满足 在 的限制。
我们在左边也枚举 ,观察 是否满足 的限制。这时,我们考虑在左区间为 的时候,右边的哪些数可以作为右端点。
他们要满足 区间在 的限制,和 区间在 的限制(称为第一,第二条限制)。他们都具有单调性。取 分别表示 满足第一条限制, 满足第二条限制。
这样我们就可以一次统计多个区间。复杂度 。主要是考虑了 的单调性。
/*
- 别摆了
- By yfz
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10, mod = 1e9+7;
int n,m,Lv[N],Rv[N];
int sum[N];
int slove(int L,int R) {
if(L == R) {
if(Lv[L] == L && Rv[L] == L) return 1;
return 0;
}
int mid = L + R >> 1;
int tmp = (slove(L,mid) + slove(mid+1,R)) % mod;
sum[mid] = 0;
for(int i=mid+1,lmR = mid+1;i<=R;i++) {
lmR = max(lmR, Rv[i]);
sum[i] = sum[i-1];
if(lmR == i) sum[i] ++;
}
for(int i=mid,lmR = mid+1,lmL = mid, realR = mid+1; i>=L ; i--) {
lmL = min(lmL, Lv[i]); lmR = max(lmR, Rv[i]);
while(realR <= R && Lv[realR] >= i) realR ++;
realR --;
if(lmL == i && realR >= lmR) {
(tmp += sum[realR] - sum[lmR - 1]) %= mod;
}
}
return tmp;
}
int main() {
// freopen("graph3.in","r",stdin);
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) Lv[i] = Rv[i] = i;
for(int i=1,x,y;i<=m;i++) {
cin>>x>>y;
Lv[x] = min(Lv[x], y), Rv[x] = max(Rv[x], y);
}
cout << slove(1,n);
return 0;
}