$n leq 100000$个点在数轴上运动,给初始位置和速度。能删$k$个点,问最晚什么时候发生第一次碰撞。
这个贪心题有点惊。。
首先肯定二分答案,然后就是判断怎么删这$k$个点。我想可以把有冲突的点连条边,虽然是平方的但可能可以用数据结构优化,实际上就是求这个图的。。最大独立集?还要一般图匹配????
结果题解告诉我,算出起点和终点,$s_i>s_j$时必须$t_i>t_j$,相当于以$s$为关键字排序找最长上升子序列。
智商-- HP--
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<math.h> 5 //#include<set> 6 //#include<queue> 7 //#include<bitset> 8 //#include<vector> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14 int qread() 15 { 16 char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1); 17 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f; 18 } 19 20 //Pay attention to '-' , LL and double of qread!!!! 21 22 int n,K; 23 #define maxn 100011 24 struct BIT 25 { 26 int a[maxn],n; 27 void clear(int N) {n=N; memset(a,0,sizeof(a));} 28 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]=max(a[x],v);} 29 int query(int x) {int ans=0; for (;x;x-=x&-x) ans=max(ans,a[x]); return ans;} 30 }t; 31 32 struct Point{int s,t,v; bool operator < (const Point &b) const {return s<b.s;} }p[maxn]; 33 struct TT{int id; double v; bool operator < (const TT &b) const {return v<b.v;} }tt[maxn]; 34 int f[maxn]; 35 bool check(double T) 36 { 37 t.clear(n); 38 for (int i=1;i<=n;i++) tt[tt[i].id=i].v=p[i].s+p[i].v*T; 39 sort(tt+1,tt+1+n); for (int i=1;i<=n;i++) p[tt[i].id].t=i; 40 int ans=0; 41 for (int i=1;i<=n;i++) 42 { 43 f[i]=t.query(p[i].t-1)+1; 44 t.add(p[i].t,f[i]); 45 ans=max(ans,f[i]); 46 } 47 // cout<<T<<endl; 48 // for (int i=1;i<=n;i++) cout<<f[i]<<' ';cout<<endl; 49 return n-ans<=K; 50 } 51 52 int main() 53 { 54 n=qread(); K=qread(); 55 for (int i=1;i<=n;i++) {p[i].s=qread(); p[i].v=qread();} 56 sort(p+1,p+1+n); 57 58 double L=0,R=1e9; 59 while (R-L>1e-4) 60 { 61 double mid=(L+R)/2.; 62 if (check(mid)) L=mid; else R=mid; 63 } 64 printf(L>1e9-1?"Forever":"%.4lf ",L); 65 return 0; 66 }