首页 > 代码库 > 奶牛跑步2

奶牛跑步2

 

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 }

 

奶牛跑步2