AtCoder Grand Contest 015 E - Mr.Aoki Incubator
阿新 • • 發佈:2018-12-05
題目傳送門:https://agc015.contest.atcoder.jp/tasks/agc015_e
題目大意:
數軸上有\(N\)個點,每個點初始時在位置\(X_i\),以\(V_i\)的速度向數軸正方向前進
初始時刻,你可以選擇一些點為其染色,之後的行走過程中,染色的點會將其碰到的所有點都染上色,之後被染上色的點亦是如此
在所有\(2^N\)種初始染色方案中,問有多少種初始染色方案,能使得最終所有的點都被染色?答案對\(10^9+7\)取模
我們考慮按速度排序,對於每個點\(i\),我們找到最左邊的\(L\)滿足\(x_L\geqslant x_i\),找到最右邊的\(R\)滿足\(x_R\leqslant x_i\)
這樣問題就轉變為了由一堆區間覆蓋線段的方案數,我們用單調佇列優化DP即可
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f #define min(x,y) (x<y?x:y) #define max(x,y) (x>y?x:y) using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int frd(){ int x=0,f=1; char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline int read(){ int x=0,f=1; char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=2e5,p=1e9+7; struct S1{ int x,v; void rd(){x=read(),v=read();} bool operator <(const S1 &tis)const{return v<tis.v;} }A[N+10]; struct S2{ int l,r; void insert(int _l,int _r){l=_l,r=_r;} bool operator <(const S2 &tis)const{return r!=tis.r?r<tis.r:l<tis.l;} }v[N+10]; int stack[N+10],top; int s[N+10],f[N+10]; int main(){ int n=read(); for (int i=1;i<=n;i++) A[i].rd(); sort(A+1,A+1+n); for (int i=1;i<=n;i++){ if (!top||A[i].x>A[stack[top]].x) stack[++top]=i; int l=1,r=top; while (l<=r){ int mid=(l+r)>>1; if (A[i].x<=A[stack[mid]].x) r=mid-1; else l=mid+1; } v[i].l=stack[l]; } top=0; for (int i=n;i>=1;i--){ if (!top||A[i].x<A[stack[top]].x) stack[++top]=i; int l=1,r=top; while (l<=r){ int mid=(l+r)>>1; if (A[stack[mid]].x<=A[i].x) r=mid-1; else l=mid+1; } v[i].r=stack[l]; } sort(v+1,v+1+n); int now=1,Ans=0; for (int i=1;i<=n;i++){ while (v[now].r<v[i].l-1) now++; f[i]=(s[i-1]-s[now-1]+p)%p; if (v[i].l==1) f[i]++; if (v[i].r==n) Ans=(Ans+f[i])%p; s[i]=(s[i-1]+f[i])%p; } printf("%d\n",Ans); return 0; }