题目


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5 + 5, mod = 1e9 + 7;
int cnt[maxn];//cnt[i]表示第i组区间覆盖当前点多少次
int mp[3];//mp[i]表示覆盖当前点i次的,有多少组区间
int pw[maxn];//2的幂次
struct Seg{
int pos, mark, id;
bool operator<(const Seg &x)const{
if(pos != x.pos)
return pos < x.pos;
return mark < x.mark;//pos相同时,必须先遍历以pos为结尾的区间
}
}seg[maxn * 4];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n, i, j;
cin >> n;
int l, r;
int m = 0;
pw[0] = 1;
for(i = 1; i <= n; i++){
pw[i] = pw[i - 1] * 2LL % mod;
cin >> l >> r;
seg[++m] = {l, 1, i};
seg[++m] = {r + 1, -1, i};
cin >> l >> r;
seg[++m] = {l, 1, i};
seg[++m] = {r + 1, -1, i};
}
sort(seg + 1, seg + m + 1);
mp[0] = n;
int res = 0;
for(i = 1; i <= m; i++){
int id = seg[i].id, pos = seg[i].pos, mark = seg[i].mark;
mp[cnt[id]]--;
cnt[id] += mark;
if(mark == 1 && !mp[0]){//只在每个区间开头且当前点被所有组区间覆盖才统计答案
res = (res + pw[mp[2]]) % mod;
}
mp[cnt[id]]++;//先判断是否统计答案再更新mp数组,考虑下面几种情况(假设当前点都被所有组区间覆盖到):
//1、当前点是该组区间的第一个区间的开头,那么先统计答案和还是更新mp,没有影响(因为mp[2]不会改变)
//2、当前点是该组第二个区间的开头,且第一个区间和第二个区间不相交,那么和1、同理
//3、当前点是第二个区间开头,第一个和第二个区间相交,且第一个区间开头(含)到第二个区间开头(不含)的点中有被所有组区间覆盖的,
//即第一个区间已经选过,那么此时mp[2]++再统计就会重复
//4、当前点是第二个区间开头,第一个和第二个区间相交,且第一个区间开头含)到第二个区间开头(不含)的点中没有有被所有组区间覆盖的,
//即第一个区间没有选过,在遍历第一组第一个区间的开头时,此时mp[2]=1,即第二组两个区间各自选的情况都会统计到
}
cout << res;
return 0;
}