agc015E Mr.Aoki Incubator

题意:

数轴上许多黑点,每个点都有一个方向向右的正速度。 

当两个点在同一个位置上重合时,若其中一个是红色,另一个也变成红色。 

保证没有相同速度或初始坐标。 

现问你有多少方法染红一些点,使得无穷久后所有点都被染红。

$N \leq 2*10^5 , X_i,V_i \leq 10^9$

这算是一道比较简单的题吧

把点按照$X_i$排序后,我们考虑第$i$个点,

找到一个最小的$L_i$满足$V[L_i] \geq V[i]$,和一个最大的$R_i$满足$V[R_i] \leq V[i]$

那么只要在$[L_i,R_i]$之间的点有一个一开始被染红,那么第$i$个点最后也会变成红色

那么也就是给你$n$个区间,你要求能保证每个区间都至少有一个点染红的方案数

前缀和优化dp。

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=2e5+7,maxt=23;
const ll mod=1e9+7;
int n,W,p[maxn],st[2][maxn][maxt],TOT;

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Node{
	int x,v;
	bool operator < (const Node& b) const{return x<b.x;}
}node[maxn];

struct Li{
	int l,r;
	Li(){}
	Li(int l,int r):l(l),r(r){}
	bool operator < (const Li& b) const{return r==b.r? l>b.l:r<b.r;}
}li[maxn];

int getl(int x) {
	int pos=1;
	Rep(i,W,0) if(st[0][pos][i]<x) pos+=(1<<i);
	return pos;
}

int getr(int x) {
	int pos=n;
	Rep(i,W,0) if(st[1][pos][i]>x) pos-=(1<<i);
	return pos;
}

ll sum[4*maxn],ql,qr,qx;
void ud(int pos) {sum[pos]=(sum[pos<<1]+sum[pos<<1|1])%mod;}
void pd(int pos) {
	if(sum[pos]!=0) return;
	sum[pos<<1]=0; sum[pos<<1|1]=0;
}
 
void chge(int pos,int l,int r) {
	if(l>=ql&&r<=qr) {
		sum[pos]=qx;
		return;
	}
	int mid=(l+r)>>1; pd(pos);
	if(ql<=mid) chge(pos<<1,l,mid);
	if(qr>mid) chge(pos<<1|1,mid+1,r);
	ud(pos);
}

int main() {
	read(n); int x,y;
	For(i,1,n) {
		read(node[i].x);
		read(node[i].v);
		p[i]=node[i].v;
	}
	sort(p+1,p+n+1);
	sort(node+1,node+n+1);
	For(i,1,n) {
		node[i].x=i;
		node[i].v=lower_bound(p+1,p+n+1,node[i].v)-p;
	}
	For(i,1,n) st[0][i][0]=st[1][i][0]=node[i].v;
	for(W=1;(1<<W)<=n;++W) {
		x=(1<<W-1);
		For(i,1,n-x) st[0][i][W]=max(st[0][i][W-1],st[0][i+x][W-1]);
		For(i,n-x+1,n) st[0][i][W]=st[0][i][W-1];
		Rep(i,n,x+1) st[1][i][W]=min(st[1][i][W-1],st[1][i-x][W-1]);
		Rep(i,x,1) st[1][i][W]=st[1][i][W-1];
	} --W;
	For(i,1,n) {
		x=getl(node[i].v);
		y=getr(node[i].v);
		li[i]=Li(x,y);
	}
	sort(li+1,li+n+1);
	For(i,1,n) p[i]=0;
	For(i,1,n) p[li[i].r]=max(p[li[i].r],li[i].l);
	For(i,2,n) p[i]=max(p[i],p[i-1]);
	TOT=n+1; ql=qr=1; qx=1; chge(1,1,TOT);
	For(i,1,n) {
		ql=qr=i+1; qx=sum[1];
		chge(1,1,TOT);
		ql=1; qr=p[i]; qx=0;
		if(ql<=qr) chge(1,1,TOT);
	}
	printf("%lld\n",sum[1]%mod);
	return 0;
}

  

posted @ 2018-05-26 13:15  shixinyi  阅读(299)  评论(0编辑  收藏  举报