1071: [SCOI2007]组队 - BZOJ

Description

NBA每年都有球员选秀环节。通常用速度和身高两项数据来衡量一个篮球运动员的基本素质。假如一支球队里速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值。这个式子很容易理解,如果一个球队的球员速度和身高差距太大,会造成配合的不协调。 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名符合条件的候选球员。
Input

第一行四个数N、A、B、C 下接N行每行两个数描述一个球员的height和speed
Output

最多候选球员数目。
Sample Input
4 1 2 10
5 1
3 2
2 3
2 1
Sample Output
4


HINT

数据范围: N <= 5000 ,height和speed不大于10000。A、B、C在长整型以内。

 

做了这道题,我深深的体会到了longint和int64时间上的差异(因为最开始用的是int64,怕乘起来会爆longint)

现在开始分析题目

把那个式子变一下,就变成了a*x+b*y<=c+a*minx+b*miny(注意x>=minx,y>=miny)

我们暴力的想法是O(n^3)先枚举minx和miny,再枚举可行的点

因为a*x+b*y是定值,所以我们先排序,在枚举枚举minx时把比minx小的点删掉,枚举miny的时候把比miny小的点删掉(注意不要重复删除)

然后可以用树状数组维护和的信息,这样是O(n^2*logn)的

但是我们可以做得更好,我们从小到大枚举minx和miny,minx确定后c+a*minx+b*miny是递增的,所以只要拿一个指针往后移加到sum里去就行了(确定minx后把信息全部赋为初值)

这样就是O(n^2)的,用pascal的同学千万别用int64,用longint快一些,int64TLE无数

  1 const

  2     maxn=5010;

  3 type

  4     aa=array[0..maxn]of longint;

  5 var

  6     n,num,a,b,c:longint;

  7     x,y,z,k,yi,zi:aa;

  8 

  9 procedure swap(var x,y:longint);

 10 var

 11     t:longint;

 12 begin

 13     t:=x;x:=y;y:=t;

 14 end;

 15 

 16 procedure sort(l,r:longint;var a,b:aa);

 17 var

 18     i,j,y:longint;

 19 begin

 20     i:=l;

 21     j:=r;

 22     y:=a[(l+r)>>1];

 23     repeat

 24       while a[i]<y do

 25         inc(i);

 26       while a[j]>y do

 27         dec(j);

 28       if i<=j then

 29       begin

 30         swap(a[i],a[j]);

 31         swap(b[i],b[j]);

 32         inc(i);

 33         dec(j);

 34       end;

 35     until i>j;

 36     if i<r then sort(i,r,a,b);

 37     if j>l then sort(l,j,a,b);

 38 end;

 39 

 40 procedure init;

 41 var

 42     i:longint;

 43 begin

 44     read(n,a,b,c);

 45     for i:=1 to n do

 46       read(x[i],y[i]);

 47     sort(1,n,x,y);

 48     for i:=1 to n do

 49       begin

 50         k[i]:=y[i];

 51         yi[i]:=i;

 52       end;

 53     sort(1,n,k,yi);

 54     for i:=1 to n do

 55       begin

 56         k[i]:=i;

 57         zi[i]:=a*x[i]+b*y[i];

 58       end;

 59     sort(1,n,zi,k);

 60     for i:=1 to n do

 61       if (zi[i]=zi[i-1]) and (i<>1) then z[k[i]]:=z[k[i-1]]

 62       else z[k[i]]:=z[k[i-1]]+1;

 63     num:=0;

 64     for i:=1 to n do

 65       if zi[i]<>zi[i-1] then

 66       begin

 67         inc(num);

 68         zi[num]:=zi[i];

 69       end;

 70 end;

 71 

 72 var

 73     vis:array[0..maxn]of boolean;

 74 

 75 procedure work;

 76 var

 77     ans,sum,i,j,l,p:longint;

 78 begin

 79     ans:=0;

 80     for i:=1 to n do

 81       begin

 82         if (i=1) or (x[i]<>x[i-1]) then

 83         begin

 84           sum:=0;

 85           l:=0;

 86           for j:=1 to num do

 87             k[j]:=0;

 88           for j:=i to n do

 89             inc(k[z[j]]);

 90           for j:=1 to n do

 91             if vis[yi[j]]=false then

 92             begin

 93               p:=c+a*x[i]+b*y[yi[j]];

 94               while (zi[l+1]<=p)and(l<num) do

 95                 begin

 96                   inc(l);

 97                   inc(sum,k[l]);

 98                 end;

 99               if ans<sum then ans:=sum;

100               if zi[l]>=a*x[yi[j]]+b*y[yi[j]] then dec(sum);

101               dec(k[z[yi[j]]]);

102             end;

103         end;

104         vis[i]:=true;

105         if i+ans>n then break;

106       end;

107     write(ans);

108 end;

109 

110 begin

111     init;

112     work;

113 end.
View Code

 

你可能感兴趣的:(2007)