题意:
数轴上许多黑点,每个点都有一个方向向右的正速度。
当两个点在同一个位置上重合时,若其中一个是红色,另一个也变成红色。
保证没有相同速度或初始坐标。
现问你有多少方法染红一些点,使得无穷久后所有点都被染红。
$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;
}