朴素的做法显然是O(n3)的
考虑优化,我们将约束条件变形为A*h+B*v<=A*minh+B*minv+c
右边是一个定值,当右边确定了minh之后,随着minv的增大,原来满足条件的且v>=minv的一定还满足条件
然后我们只要先对A*h+B*v排序,然后穷举minh,然后扫一遍即可
O(n2)的算法很显然,我正好卡着时限过去的……
但这道题的本意肯定是有O(nlogn)的算法,求教导
1 type node=record 2 h,v,s:longint; 3 end; 4 5 var f,v:array[0..10010] of longint; 6 h:array[0..10010] of boolean; 7 w:array[0..5010] of node; 8 ans,t,m,x,y,n,i,j,sum,s,a,b,c,k:longint; 9 10 procedure swap(var a,b:node); 11 var c:node; 12 begin 13 c:=a; 14 a:=b; 15 b:=c; 16 end; 17 18 procedure sort(l,r: longint); 19 var i,j,x: longint; 20 begin 21 i:=l; 22 j:=r; 23 x:=w[(l+r) div 2].s; 24 repeat 25 while w[i].s<x do inc(i); 26 while x<w[j].s do dec(j); 27 if not(i>j) then 28 begin 29 swap(w[i],w[j]); 30 inc(i); 31 j:=j-1; 32 end; 33 until i>j; 34 if l<j then sort(l,j); 35 if i<r then sort(i,r); 36 end; 37 38 begin 39 readln(n,a,b,c); 40 for i:=1 to n do 41 begin 42 readln(x,y); 43 h[x]:=true; 44 if x>m then m:=x; 45 v[y]:=1; 46 w[i].h:=x; 47 w[i].v:=y; 48 w[i].s:=a*x+b*y; 49 end; 50 sort(1,n); 51 for i:=1 to 10000 do 52 if v[i]=1 then 53 begin 54 inc(t); 55 f[t]:=i; //表示v可能的数字 56 end; 57 58 for i:=1 to m do 59 begin 60 if not h[i] then continue; //穷举minh 61 fillchar(v,sizeof(v),0); 62 sum:=0; 63 k:=1; 64 for j:=1 to t do 65 begin 66 if j<>1 then 67 sum:=sum-v[f[j-1]]; //对于当前minv,小于的不算 68 s:=a*i+b*f[j]+c; 69 while (k<=n) and (w[k].s<=s) do 70 begin 71 if (w[k].h>=i) and (w[k].v>=f[j]) then 72 begin 73 inc(sum); 74 inc(v[w[k].v]); //方便随着minv的增大,快速减去小于minv的数目 75 end; 76 inc(k); 77 end; 78 if sum>ans then ans:=sum; 79 if k>n then break; //后面一定只减不增 80 end; 81 end; 82 writeln(ans); 83 end.