P3533 [JZOJ/NOIP] 火柴排队
给你两个序列 \(a\{\},b\{\}\),求 \(\sum (a_i-b_i)^2\) 的最小值。
可知:
\[\sum(a_i-b_i)^2=\sum {a_i}^2+{b_i}^2-2 \times \sum a_i \times b_i
\]
然后我们可以知道,让这个东西最小,就必须让 \(\sum a_i \times b_i\) 最大。同时,我们可以随便列一个方程可知当 \(a_i\) 和 \(b_i\) 最接近的时候是最大的。
至此。
Const
total=100010;
var
num,place:array[-1..total*2,1..2] of int64;
ans:array[-1..total*2] of longint;
tree:array[-1..total*5] of int64;
n,an,find:int64;
i:longint;
procedure Query(l,r,k:longint);
var mid:longint;
begin
if (1<=l)and(r<=ans[i]) then begin inc(find,tree[k]); exit; end;
mid:=(l+r) >> 1;
if 1<=mid then Query(l,mid,k << 1);
if ans[i]>mid then Query(mid+1,r,k << 1+1);
end;
procedure Change(l,r,k:longint);
var mid:longint;
begin
if l=r then begin inc(tree[k]); exit; end;
mid:=(l+r) >> 1;
if ans[i]<=mid then Change(l,mid,k << 1) else Change(mid+1,r,k << 1+1);
tree[k]:=tree[k << 1]+tree[k << 1+1];
end;
procedure Sort(l,r,kind:longint);
var
s,i,j:longint;
t:int64;
begin
i:=l; j:=r; s:=num[(l+r) >> 1,kind];
repeat
while num[i,kind]<s do i:=i+1;
while num[j,kind]>s do j:=j-1;
if i<=j then
begin
t:=num[i,kind]; num[i,kind]:=num[j,kind]; num[j,kind]:=t;
t:=place[i,kind]; place[i,kind]:=place[j,kind]; place[j,kind]:=t;
inc(i); dec(j);
end;
until i>=j;
if i<r then Sort(i,r,kind);
if j>l then Sort(l,j,kind);
end;
begin
read(n); an:=0;
for i:=1 to n do begin read(num[i,1]); place[i,1]:=i; end;
for i:=1 to n do begin read(num[i,2]); place[i,2]:=i; end;
Sort(1,n,1); Sort(1,n,2);
for i:=1 to n do ans[place[i,2]]:=place[i,1];
i:=n; Change(1,n,1);
for i:=n-1 downto 1 do
begin
find:=0; Query(1,n,1); inc(an,find);
Change(1,n,1); an:=an mod 99999997;
end;
writeln(an);
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿

浙公网安备 33010602011771号