I:Non-Puzzle: Segment Pair
题目链接:登录—专业IT笔试面试备考平台_牛客网
题目大意:
给n对区间,要求每对区间恰好选一个使得选出来的n个区间有交集,问有多少方案数
解题思路:
求以每个点为起点的n个区间交集有多少种方案数。
代码:
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define double long double
using namespace std;
const int maxn=5e5+50;
const ll mod=1e9+7;
int c1[maxn];//能到达某个点的区间数
int c2[maxn];//能到达某个点的一对区间的交集区间数,即有几个区间选择时方案数*2
int nw1[maxn];//以某个点为起点的区间数
int nw2[maxn];//以某个点为起点的一对区间的交集区间数
ll qpow(ll a,ll t){//快速幂
ll res=1;
while(t>0)
{
if(t%2==1)
{
res=res*a%mod;
}
a=a*a%mod;
t/=2;
}
return res;
}
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int l1,r1,l2,r2;
cin>>l1>>r1>>l2>>r2;
if(l1>l2)
{
swap(l1,l2);
swap(r1,r2);
}
if(r1<l2)//两个区间不重合,(l1<=r1<l2<=r2)
{
c1[l1]++;
c1[r1+1]--;
c1[l2]++;
c1[r2+1]--;
nw1[l1]++;
nw1[l2]++;
}
else
{
c1[l1]++;
c1[max(r1,r2)+1]--;
c2[l2]++;
c2[min(r1,r2)+1]--;
nw1[l1]++;
nw2[l2]++;
}
}
for(int i=1;i<=maxn;i++)//前缀和处理
{
c1[i]+=c1[i-1];
c2[i]+=c2[i-1];
}
ll res=0;
for(int i=0;i<=maxn;i++)
{
if(c1[i]!=n)
{
continue;
}
if(c1[i]-nw1[i]==n)//i点的区间数-以i为起点的区间数=i在i-1中已经被统计的方案数
{
res=(res+qpow(2,c2[i])+mod-qpow(2,c2[i]-nw2[i]))%mod;
//qpow(2,c2[i])是i的方案数
//qpow(2,c2[i]-nw2[i])是i-1已经统计过的方案数
}
else
{
res=(res+qpow(2,c2[i]))%mod;
}
}
cout<<res<<"\n";
return ;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// int T;
// cin>>T;
// while(T--)
// {
// solve();
// }
solve();
return 0;
}