Live2D

[20191006机房测试] 矿石

众所周知,九条可怜家里有矿
你可以把可怜家的矿场抽象成一条数轴,可怜家有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;
}
posted @ 2019-10-06 14:55  tqr06  阅读(207)  评论(1编辑  收藏  举报