[离散化][二分]JZOJ 5892 矿石

Description

 

Input

Output

 

Sample Input

3 2
7 11
1 5
3 8
4
7

Sample Output

5
 

Data Constraint

分析

x为该点可以采的矿石种类量

一个点的方案数为2^k-1

那么当前点可以采的矿石种类量和之前的重叠了y中,而没有重叠的为z种

方案数则为(2^y)*(2^z -1)

然后我们给点的位置离散化,在里面二分找l,r的位置,然后记录到前缀和数组里就行了

 

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll P=998244353;
ll pow[N];
ll dif[N],sam[N];
ll l[N],r[N],a[N];
int n,m;

int main() {
    freopen("ore.in","r",stdin);
    freopen("ore.out","w",stdout);
    scanf("%d%d",&n,&m);
    pow[0]=1ll;
    for (int i=1;i<=n;i++) pow[i]=pow[i-1]*2ll%P;
    for (int i=1;i<=n;i++) scanf("%lld%lld",&l[i],&r[i]);
    for (int i=1;i<=m;i++) scanf("%lld",&a[i]);
    sort(a+1,a+m+1);
    for (int i=1;i<=n;i++) {
        int fir=lower_bound(a+1,a+m+1,l[i])-a,
        las=upper_bound(a+1,a+m+1,r[i])-a;
        if (a[fir]<=r[i]) dif[fir]++;
        if (fir<las) sam[fir+1]++,sam[las]--;
    }
    ll ans=0;
    for (int i=1;i<=m;i++) {
        (sam[i]+=sam[i-1])%=P;
        (ans+=(pow[dif[i]]-1ll)*pow[sam[i]]%P)%=P;
    }
    printf("%lld",ans);
    fclose(stdin);fclose(stdout);
}
View Code

 

posted @ 2018-10-14 20:48  Vagari  阅读(196)  评论(0编辑  收藏  举报