【BZOJ4868】期末考试(整数三分)
题意:
有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布。第i位同学希望在第ti天
或之前得知所.有.课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程
公布成绩,每等待一天就会产生C不愉快度。对于第i门课程,按照原本的计划,会在第bi天公布成绩。有如下两种
操作可以调整公布成绩的时间:1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天
,公布课程Y成绩的时间提前一天;每次操作产生A不愉快度。2.增加一部分老师负责学科Z,这将导致学科Z的出成
绩时间提前一天;每次操作产生B不愉快度。上面两种操作中的参数X,Y,Z均可任意指定,每种操作均可以执行多次
,每次执行时都可以重新指定参数。现在希望你通过合理的操作,使得最后总的不愉快度之和最小
1<=N,M,Ti,Bi<=100000,0<=A,B<=100000,c<=10^16
思路:显然一堆线性函数之和一定是一个线性函数,整数三分即可 O(n log 1.5 n)
O(n)做法:
1 const oo=1<<60; 2 var b,t:array[1..200000]of longint; 3 n,m,i,l,r,mid,mid1,mid2:longint; 4 a1,b1,c1,ans,s1,s2:int64; 5 6 function max(x,y:longint):longint; 7 begin 8 if x>y then exit(x); 9 exit(y); 10 end; 11 12 function min(x,y:int64):int64; 13 begin 14 if x<y then exit(x); 15 exit(y); 16 end; 17 18 function clac(x:longint):int64; 19 var i:longint; 20 s,tmp:int64; 21 begin 22 clac:=0; 23 for i:=1 to n do 24 if t[i]<x then 25 begin 26 if x-t[i]>(oo-clac) div c1 then exit(oo); 27 clac:=clac+c1*(x-t[i]); 28 end; 29 30 31 s:=0; 32 for i:=1 to m do 33 if b[i]<x then s:=s+x-b[i]; 34 for i:=1 to m do 35 if b[i]>x then 36 begin 37 tmp:=b[i]-x; 38 if a1<b1 then 39 begin 40 if s>=tmp then 41 begin 42 clac:=clac+a1*tmp; 43 s:=s-tmp; 44 end 45 else 46 begin 47 clac:=clac+a1*s+b1*(tmp-s); 48 s:=0; 49 end; 50 end 51 else clac:=clac+b1*tmp; 52 end; 53 54 end; 55 56 begin 57 assign(input,'bzoj4868.in'); reset(input); 58 assign(output,'bzoj4868.out'); rewrite(output); 59 readln(a1,b1,c1); 60 readln(n,m); 61 r:=1; 62 for i:=1 to n do 63 begin 64 read(t[i]); 65 r:=max(r,t[i]); 66 end; 67 for i:=1 to m do 68 begin 69 read(b[i]); 70 r:=max(r,b[i]); 71 end; 72 l:=1; ans:=1<<60; 73 while l<=r do 74 begin 75 mid:=(l+r)>>1; 76 mid1:=(l+mid)>>1; mid2:=(mid+1+r)>>1; 77 s1:=clac(mid1); s2:=clac(mid2); 78 ans:=min(ans,s1); ans:=min(ans,s2); 79 if s1<=s2 then r:=mid2-1 80 else l:=mid1+1; 81 end; 82 writeln(ans); 83 84 close(input); 85 close(output); 86 end.
null