【CF56E】Domino Principle(线性扫描,伪DP)

每块多米诺骨牌所在的位置设为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.
View Code
原文地址:https://www.cnblogs.com/myx12345/p/5517728.html