众所周知,九条可怜家里有矿
你可以把可怜家的矿场抽象成一条数轴,可怜家有n种矿,第i种矿可以从[li,ri] 中的任意位置开采得到
这个暑假,地理老师给了 可怜一个列表:她的暑假作业就是收集齐这些矿石
为了保证可怜的安全,可怜的爸爸选定了m个相对安全的采矿点,第i个采矿点的坐标为ai
可怜只能选择其中一个采矿点开采她需要的矿石
可怜是一个马虎的女孩子。暑假刚开始没多久,可怜就把老师的列表弄丢了
唯一的线索是,列表上的所有矿石都是可怜家有的,则一共有2^n-1种可能的列表
现在想要知道,在所有的可能的任务列表中,有多少种是她能够在某一个安全的采矿点收集齐的


\[\text{tqr乱搞的图片与此题无强关联性……}\]

今天的题过于水了,由于矿脉成连续分布
所以只需要统计这个采矿点和上个采矿点的差异
即,多了哪些矿,少了哪些矿。就好了

代码:

#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;

int n,m,loc[100005];
ll ans=0,two[100005];

struct Stone
{
    int l,r;
    bool operator < (const Stone &a) const
    {
        return a.r<r;
    };
}a[100005];

bool cmp(Stone a,Stone b) {return a.l==b.l?a.r<b.r:a.l<b.l;}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

priority_queue<Stone> q;

inline void init()
{
    two[0]=1;
    for(register int i=1;i<=n;++i) two[i]=(two[i-1]<<1)%mod;
    for(register int i=0;i<n;++i) two[i]--;
    sort(a+1,a+n+1,cmp);
    sort(loc+1,loc+m+1);
}

int main()
{
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    read(n);read(m);
    for(register int i=1;i<=n;++i)
    {
        read(a[i].l);
        read(a[i].r);
    }
    for(register int j=1;j<=m;++j) read(loc[j]);
    init();
    int now=1;
    for(register int i=1;i<=m;++i)
    {
        while(!q.empty())
        {
            if(q.top().r<loc[i]) q.pop();
            else break;
        }
        int presiz=q.size();
        while(a[now].l<=loc[i])
        {
            if(now>n) break;
            if(a[now].r>=loc[i]) q.push(a[now]);
            now++;
        }
        int nowsiz=q.size();
        ans=(ans+two[nowsiz]-two[presiz])%mod;
    }
    ans=(ans+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}
02-14 03:43