POJ 1328
题目大意:求在x轴上放一些半径为d的圆,问至少多少个能将n个点覆盖,多组询问。
解:原来想着:线段树+heap,可是看着这一个个0ms,不敢切,以后有时间切切看虐自己。正解是先把可行圆心区间求出来,然后求最多的不互斥区间(因为区间相斥的话,说明有共点,于是不用分配多一个雷达了),证明是首先如果当前l>rrr,inc(s), 若有l<rrr and r<rrr则新预设雷达于r,rrr:=r;
好像有种隐约敢,说不出来,好难受,还是以后想透彻了再补
本题的trick点也很多,例如,d<0, y<0,注意y=0竟然是合法的!!wa了两次,囧
View Code
1 //RadarInstallation 2 const 3 maxn=1111; 4 inf='1.txt'; 5 def=1e-10; 6 type 7 data=record 8 l, r: double; 9 end; 10 var 11 line: array[0..maxn]of data; 12 test, n, d, ans: longint; 13 procedure qsort(b, e: longint); 14 var 15 i, j: longint; 16 x: double; 17 k: data; 18 begin 19 i := b; j := e; x := line[(i+j)>>1].l; 20 repeat 21 while line[i].l<x do inc(i); 22 while line[j].l>x do dec(j); 23 if i<=j then begin 24 k := line[i]; line[i] := line[j]; line[j] := k; 25 inc(i); dec(j); 26 end; 27 until i>j; 28 if j>b then qsort(b, j); 29 if i<e then qsort(i, e); 30 end; 31 32 procedure init; 33 var 34 i, x, y: longint; 35 tmp: double; 36 begin 37 ans := 0; 38 for i := 1 to n do begin 39 readln(x, y); 40 with line[i] do begin 41 if (y<0)or(y>d) then begin ans := -1; continue; end; 42 if y=d then tmp := 0 43 else tmp := sqrt(sqr(d)-sqr(y)); 44 l := x - tmp; r := x + tmp; 45 end; 46 end; 47 if ans=-1 then exit; 48 qsort(1, n); 49 end; 50 51 procedure main; 52 var 53 rrr: double; 54 i: longint; 55 begin 56 rrr := -maxlongint; 57 for i := 1 to n do with line[i] do begin 58 if l{+def}>rrr then begin 59 inc(ans); 60 rrr := r; 61 end 62 else begin 63 if r<rrr then rrr := r; 64 end; 65 end; 66 end; 67 68 procedure print; 69 begin 70 writeln('Case ',test,': ', ans); 71 end; 72 73 begin 74 assign(input,inf); reset(input); 75 readln(n, d); 76 test := 0; 77 while (n<>0)or(d<>0) do begin 78 inc(test); 79 init; 80 if ans=0 then main; 81 print; 82 readln; 83 readln(n, d); 84 end; 85 end.