絕渡逢舟系列題解

2021-07-09 12:34:34 字數 4412 閱讀 9934

題目大意

按順時針或逆時針給定凸包上的n個點,隨機選取內部或邊上的整點,求兩點為正方形對角線的正方形面積的期望題解有

sum 個合法點(內部或邊上),那麼面積的期望為 an

s=12

∑sum

i=1∑

sumj

=1(x

i−xj

)2+(

yi−y

j)2n

⋅(n−

1)對於分子x和

y是同一

形式所以我們只看∑s

umi=

1∑su

mj=1

(xi−

xj)2

開啟括號後我們得到 ∑i

∑j(x

i2+x

j2)−

2⋅∑i

∑jxi

⋅xj=

2⋅su

m⋅∑i

xi2−

2⋅(∑

ixi)

2 這樣我們只需要求兩個字首和即可

剩下的問題就是統計所有點的個數和座標

如果暴力用掃瞄線去掃會t,但是我們發現對於一條掃瞄線所掃到的點

x 座標相同,所以用個數*座標值直接計入即可

一條掃瞄線同一時間會掃到凸包上的兩條邊,用交到的兩個點求一下個數即可

const

maxn=100005;

maxm=1000005;

var x,y:array[0..maxn]of int64;

wy,wx:array[0..maxm*2,1..2]of real; // k=(y1-y2)/(x1-x2); b=(x1y2-x2y1)/(x1-x2);

i,j,k:longint;

n,l,r,u,d,e,f,***,yyy:longint;

sum,summ,a,b,c:int64;

ans,x1,x2,y1,y2:real;

procedure

swap

(var a,b:real);

var c:real;

begin

c:=a; a:=b; b:=c;

end;

function

xx(a:real):int64;

begin

if trunc(a)then

exit(trunc(a)+1)

else

exit(trunc(a));

end;

function

g(a,b:real):int64;

var d,c:int64;

begin

d:=trunc(b);

c:=xx(a);

exit(d-c+1);

end;

begin

assign(input,'square.in'); assign(output,'square.out'); reset(input); rewrite(output);

readln(n);

readln(x[1],y[1]);

l:=x[1]; r:=x[1]; u:=y[1]; d:=y[1];

x[n+1]:=x[1]; y[n+1]:=y[1];

for i:=2

to n do

begin

readln(x[i],y[i]);

if x[i]then l:=x[i];

if x[i]>r then r:=x[i];

if y[i]then d:=y[i];

if y[i]>u then u:=y[i];

end;

for i:=0

to r-l do

begin

wx[i,1]:=maxm;

wx[i,2]:=maxm;

end;

for i:=0

to u-d do

begin

wy[i,1]:=maxm;

wy[i,2]:=maxm;

end;

***:=l; yyy:=d;

if ***<0

then inc(x[1],-***);

if yyy<0

then inc(y[1],-yyy);

l:=maxm; r:=-maxm; u:=-maxm; d:=maxm;

for i:=2

to n+1

dobegin

if ***<0

then inc(x[i],-***);

if yyy<0

then inc(y[i],-yyy);

if x[i]then l:=x[i];

if x[i]>r then r:=x[i];

if y[i]then d:=y[i];

if y[i]>u then u:=y[i];

if x[i]=x[i-1]

then

begin a:=0; b:=1; c:=x[i]; end

else

begin a:=y[i]-y[i-1]; b:=x[i]-x[i-1]; c:=x[i]*y[i-1]-x[i-1]*y[i]; end;

if x[i]1]

then

begin e:=x[i]; f:=x[i-1]; end

else

begin e:=x[i-1]; f:=x[i]; end;

for j:=e to f-1

doif wx[j,1]=maxm

then wx[j,1]:=(a*j+c)/b

else

if wx[j,2]=maxm

then wx[j,2]:=(a*j+c)/b;

if y[i]=y[i-1]

then

begin a:=1; b:=0; c:=-y[i]; end

else

begin a:=y[i]-y[i-1]; b:=x[i]-x[i-1]; c:=x[i]*y[i-1]-x[i-1]*y[i]; end;

if y[i]1]

then

begin e:=y[i]; f:=y[i-1]; end

else

begin e:=y[i-1]; f:=y[i]; end;

for j:=e to f-1

doif wy[j,1]=maxm

then wy[j,1]:=(j*b-c)/a

else

if wy[j,2]=maxm

then wy[j,2]:=(j*b-c)/a;

end;

sum:=0;

for i:=l to r do

begin

if wx[i,1]>wx[i,2] then swap(wx[i,1],wx[i,2]);

sum:=sum+g(wx[i,1],wx[i,2]);

end;

x1:=0; x2:=0;

for i:=l to r do

begin

x1:=x1+(g(wx[i,1],wx[i,2])*int64(i));

x2:=x2+(g(wx[i,1],wx[i,2])*int64(i)*int64(i));

end;

ans:=0;

ans:=(2*sum*x2-2*x1*x1)/2/sum/(sum-1);

y1:=0; y2:=0;

for i:=d to u do

begin

if wy[i,1]>wy[i,2] then swap(wy[i,1],wy[i,2]);

y1:=y1+(g(wy[i,1],wy[i,2])*int64(i));

y2:=y2+(g(wy[i,1],wy[i,2])*int64(i)*int64(i));

end;

ans:=ans+(2*sum*y2-2*y1*y1)/2/sum/(sum-1);

writeln(ans:0:10);

close(input); close(output);

end.

亦或問題

題目大意給定

n(n≤

50000)個

數,詢問

前m大的

aixo

raj的

和題解首先

因為每對

會出現2

次,所以

最後要除

以2,我

們考慮求

前2∗m

大的答案

亦或,還是最值

相關,我

們對所有

數建立t

rie樹

如果我們求出了第2∗

m 大的得數是多少,我們只要對每個數求出它亦或別的數後大於2∗

m 大的數的和計入答案即可

具體來說就是,