P1443 - 【USACO】奶牛跑步2
Description
FJ的N(1 <= N <= 100,000)头奶牛们又兴高采烈地出来运动了!她们在一条无限长的小路上跑步,每头牛起跑的位置都不同,速度也不尽相同。
道路中划出了若干条跑道,以便她们能快速"超车",同一跑道中的任意两头牛都不会出现在相同的位置。不过FJ不愿让任何一头牛更换跑道或者调整速度,他想知道如果让牛们跑足T(1 <= T <=
1,000,000,000)分钟的话,至少需要多少条跑道才能满足需要。
Input
第一行有两个数,N和T;
接下来有N行,每一行两个数,表示一头牛的位置和速度,其中位置是一个非负整数,速度为一个正整数,均不超过10^9。所有牛的开始位置均不相同,因此N头牛的数据将以位置升序的方式给出。
Output
输出为一个整数,表示所需跑道的最小数目,要保证同一跑道中的任意两头牛在T时限内(到第T分钟结束)不会撞到一起。
Sample Input
5 3
0 1
1 2
2 3
3 2
6 1
Sample Output
3
Hint
Source
USACO
基本 ,平衡树
首先得到一个式子,xi+vi*T < xj+vj*T,若j与i满足这个条件,则j可以放在i后面,与i用一个跑道,意思是i无论如何都无法再T时间内追上j。但有很多个点满足,因为把j放入跑道之后,这条跑道的条件就要用j的信息来判断了,所以要使损失最小,则应该把j放到所有满足条件的值最大的那个后面,所以此时应该贪心一个一个的加入,用平衡树来实现查找,然后删除这个前驱,加入这个点。若没有前驱则表示没有满足条件的,需增加一个跑道,此时ans++;
1 #include<map> 2 #include<set> 3 #include<cmath> 4 #include<ctime> 5 #include<queue> 6 #include<stack> 7 #include<cstdio> 8 #include<vector> 9 #include<cstdlib> 10 #include<cstring> 11 #include<iomanip> 12 #include<iostream> 13 #include<algorithm> 14 #define ll long long 15 #define rep(i,a,b) for(register int i=a;i<=b;i++) 16 #define re register 17 #define il inline 18 using namespace std; 19 const int N=100010; 20 int pre[N],cnt[N],ch[N][2],n,root,tot; 21 ll key[N],T; 22 il ll gl() { 23 ll ret=0;char ch=getchar(); 24 while(ch<‘0‘||ch>‘9‘) ch=getchar(); 25 while(ch>=‘0‘&&ch<=‘9‘) ret=ret*10+ch-‘0‘,ch=getchar(); 26 return ret; 27 } 28 il int getx(int x) {return ch[pre[x]][1] == x;} 29 il void Newnode(int fa,ll v) { 30 ++tot; 31 pre[tot]=fa , cnt[tot]=1; 32 key[tot]=v; 33 } 34 il void Rotate(int x) { 35 int old=pre[x],oldx=pre[old],bj=getx(x); 36 ch[old][bj]=ch[x][!bj];pre[ch[old][bj]]=old; 37 ch[x][!bj]=old;pre[old]=x; 38 pre[x]=oldx; 39 if(oldx) ch[oldx][ch[oldx][1]==old]=x; 40 } 41 il void Splay(int x,int goal) { 42 while(pre[x]!=goal) { 43 if(pre[pre[x]]==goal) Rotate(x); 44 else { 45 int no=getx(x),od=getx(pre[x]); 46 if(no==od) Rotate(pre[x]),Rotate(x); 47 else Rotate(x),Rotate(x); 48 } 49 } 50 if(goal==0) root=x;// bug 51 } 52 il void Insert(ll v) { 53 if(root==0) { 54 Newnode(0,v);root=tot;return; 55 } 56 int now=root,fa=0; 57 while(1) { 58 if(key[now]==v) { 59 cnt[now]++;Splay(now,0);return; 60 } 61 fa=now; 62 now=ch[now][v > key[now]]; 63 if(now==0) { 64 Newnode(fa,v); 65 ch[fa][v > key[fa]] = tot; 66 Splay(tot,0); 67 return; 68 } 69 } 70 } 71 il int get_pre() { 72 int now=ch[root][0]; 73 while(ch[now][1]) now=ch[now][1]; 74 return now; 75 } 76 il void del(int x) { 77 if(root==0) return; 78 Splay(x,0); 79 if(cnt[x]>1) {cnt[x]--;return;} 80 if(!ch[x][0]&&!ch[x][1]) { 81 root=0;return; 82 } 83 if(!ch[x][0]) { 84 root=ch[x][1];pre[root]=0; 85 return; 86 } 87 else if(!ch[x][1]) { 88 root=ch[x][0];pre[root]=0; 89 return; 90 } 91 int l=get_pre(); 92 Splay(l,0);// 93 ch[root][1]=ch[x][1]; 94 pre[ch[x][1]]=root;// bug 95 ch[x][1]=ch[x][0]=cnt[x]=0;// 96 return; 97 } 98 int find(ll k) {// 找到 <= k 的最大数 99 int ret=-1,now=root; 100 while(now) { 101 if(key[now] < k) ret=now,now=ch[now][1]; 102 else now=ch[now][0]; 103 } 104 return ret; 105 } 106 int main() { 107 scanf("%d",&n);T=gl(); 108 re ll x,v,S; 109 int ans=0; 110 rep(i,1,n) { 111 x=gl(),v=gl(),S=x+v*T; 112 int cur=find(S); 113 if(cur==-1) ans++; 114 else del(cur); 115 Insert(S); 116 } 117 cout<<ans; 118 return 0; 119 }
时间: 2024-10-26 19:16:40