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