ZROI2018提高day3t2

时间:2023-03-10 05:23:40
ZROI2018提高day3t2

传送门

分析

我们设A[i]表示点i有几个矿,B[i]表示这之中有几个矿是第一次出现,所以点i的贡献即为

(2^B[i]-1)*(2^(A[i]-B[i]))

注意减一的原因是第一次出现的矿应至少有一个。然后我们用set维护一下就可以了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const long long mod = ;
struct node {
long long x,y;
};
node d[];
set<long long>s;
inline bool cmp(const node a,const node b){
if(a.x==b.x)return a.y>b.y;
return a.x<b.x;
}
long long pw2[];
int main(){
long long n,m,sum=,ans=,i,j,k,cnt=;
scanf("%lld%lld",&n,&m);
pw2[]=;
for(i=;i<=n;i++)pw2[i]=pw2[i-]*%mod;
for(i=;i<=n;i++){
long long x,y;
scanf("%lld%lld",&x,&y);
d[++cnt].x=x,d[cnt].y=i;
d[++cnt].x=y,d[cnt].y=-i;
}
for(i=;i<=m;i++){
long long x;
scanf("%lld",&x);
d[++cnt].x=x;
}
sort(d+,d+cnt+,cmp);
for(i=;i<=cnt;i++){
if(!d[i].y){
ans=(ans+(pw2[s.size()]-)*pw2[sum-s.size()]%mod)%mod;
s.clear();
}
if(d[i].y>)s.insert(d[i].y),sum++;
if(d[i].y<)s.erase(-d[i].y),sum--;
}
printf("%lld\n",ans);
return ;
}