LGP6146题解

思维僵化了,习惯按照右端点排序,没想到是按照左端点排序。。。

考虑从左到右依次加入线段,考虑贡献。

设前 \(i\) 条线段的答案为 \(dp[i]\)

考虑两种情况:

  1. 不加,贡献为 \(dp[i-1]\)

  2. 加,首先贡献有 \(dp[i-1]\),还有可能额外多出连通块。

考虑哪些集合会多出连通块。这些集合最右边的点明显不能超过第 \(i\) 条线段的左端点。只需要数出即可,做一个前缀和即可。

设这些线段有 \(x\) 条,多出的集合贡献是 \(2^x\)

\[dp[i]=2\times dp[i-1]+2^x \]

#include<algorithm>
#include<cstdio>
typedef unsigned ui;
const ui M=1e5+5,mod=1e9+7;
ui n,ans,pw2[M],S[M<<1];
struct line{
	ui L,R;
	inline bool operator<(const line&it)const{
		return L<it.L;
	}
}l[M];
signed main(){
	scanf("%u",&n);pw2[0]=1;
	for(ui i=1;i<=n;++i)scanf("%u%u",&l[i].L,&l[i].R),++S[l[i].R];std::sort(l+1,l+n+1);
	for(ui i=1;i<=(n<<1);++i)S[i]+=S[i-1];
	for(ui i=1;i<=n;++i)pw2[i]=pw2[i-1]*2%mod,ans=(ans*2+pw2[S[l[i].L-1]])%mod;
	printf("%u",ans);
}
posted @ 2022-02-28 11:22  Prean  阅读(21)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};