1. 程式人生 > >NOI熱身賽A. 小w、小j和小z

NOI熱身賽A. 小w、小j和小z

必須 ans 告訴 i++ ons bool IV define 圖片

$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\n",L); 65 return 0; 66 }
View Code

NOI熱身賽A. 小w、小j和小z