每块多米诺骨牌所在的位置设为x,每块多米诺骨牌高度为h。如果将x位置上的多米诺骨牌向右翻到,它就可以影响[x+1, x+h-1]范围内的所有多米诺骨牌,让他们也翻到,同时这些被翻到的多米诺骨牌还能影响到其他多米诺骨牌,现在BSNY给出n块多米诺骨牌的位置和高度,问如果向右翻到第i块多米诺骨牌,会有多少多米诺骨牌翻到。
按左端点排序,然后线性扫描。其实二分也可以,但答案有部分的重叠,即单调性。
1 var x,h,d,c,ans:array[1..200000]of longint; 2 n,i,k,last:longint; 3 4 procedure swap(var x,y:longint); 5 var t:longint; 6 begin 7 t:=x; x:=y; y:=t; 8 end; 9 10 procedure qsort(l,r:longint); 11 var i,j,mid:longint; 12 begin 13 i:=l; j:=r; mid:=x[(l+r)>>1]; 14 repeat 15 while mid>x[i] do inc(i); 16 while mid<x[j] do dec(j); 17 if i<=j then 18 begin 19 swap(x[i],x[j]); 20 swap(h[i],h[j]); 21 swap(c[i],c[j]); 22 swap(d[i],d[j]); 23 inc(i); dec(j); 24 end; 25 until i>j; 26 if l<j then qsort(l,j); 27 if i<r then qsort(i,r); 28 end; 29 30 begin 31 32 readln(n); 33 for i:=1 to n do 34 begin 35 readln(x[i],h[i]); 36 d[i]:=x[i]+h[i]-1; 37 c[i]:=i; 38 end; 39 qsort(1,n); 40 ans[c[n]]:=1; 41 for i:=n-1 downto 1 do 42 begin 43 last:=d[i]; 44 k:=i+1; 45 ans[c[i]]:=1; 46 while true do 47 begin 48 if k>n then break; 49 if x[k]<=last then ans[c[i]]:=ans[c[i]]+ans[c[k]] 50 else break; 51 k:=k+ans[c[k]]; 52 end; 53 end; 54 for i:=1 to n-1 do write(ans[i],' '); 55 writeln(ans[n]); 56 57 end.