JZOJ6217 Area 計算幾何

2021-09-24 12:24:34 字數 3676 閱讀 6522

給定平面上的n個點,記為a

1...na_

a1...n

​現在給出q組詢問,每次給出乙個向量p,你需要找乙個區間[l,

r]

[l,r]

[l,r

],使得2∑i

=lrs

δopa

i2\sum\limits_^s_

2i=l∑r

​sδo

pai​

​最大,輸出這個最大值。

n<=100000,q<=1000000,座標絕對值<=1e9

把每個點看做乙個向量,如果我們把所有的區間的和向量提出來,那麼顯然最大的那個一定在凸包上。

但直接做凸包是o(n

2log⁡n

)o(n^2\log n)

o(n2

logn

)的,顯然不行

我們考慮分治計算這個凸包。

記當前分治區間為[l,

r]

[l,r]

[l,r

],我們需要求出所有左右端點在[l,

r]

[l,r]

[l,r

]內的所有區間[x,

y]

[x,y]

[x,y

]的和向量的凸包。

如果x

<=y

<=m

id

x<=y<=mid

x<=y

<=m

id或m id

<

x<=y

midmi

d<

x<=y

,那麼直接分治兩邊

我們只需要考慮跨過的情況。

可以發現跨過的都能分成[x,

mid]

+[mi

d+1,

y]

[x,mid]+[mid+1,y]

[x,mid

]+[m

id+1

,y],實際上就是左邊右端點為mid和右邊左端點為mid+1的兩部分的閔可夫斯基和(即兩個點集兩兩座標相加)。

有結論,兩個凸包的閔可夫斯基和的凸包,總點數是o(原凸包點數和),並且新凸包的邊斜率和長度都會是原本兩個凸包上的某條邊。

那麼我們直接暴力求出這兩個凸包,各找到最左下的點,然後類似歸併排序的掃一遍就完成了凸包的合併。

這樣我們最後得到了o(n

)o(n)

o(n)

個凸包,總點數和是o(n

log⁡n)

o(n\log n)

o(nlogn)

的。凸包並?

不需要,我們直接把o(n

log⁡n)

o(n\log n)

o(nlogn)

個凸包拉出來暴力再建一次即可。

查詢的時候,我們可以把所有詢問極角排序,顯然最優點在凸包上是單調的,直接用個指標掃(可以用於詢問向量的叉積變號處來判斷)

也可以對於每個詢問在凸包上二分。

實現細節較多。

複雜度o(n

log⁡2n

)o(n\log^2 n)

o(nlog2n

)

#include

#define fo(i,a,b) for(int i=a;i<=b;++i)

#define fod(i,a,b) for(int i=a;i>=b;--i)

typedef

long

long ll;

const

int n=

100005

;const

double pi=

acos(-

1);using

namespace std;

int n,q;

struct node

}ask[n*10]

,ap[n]

,ar[

20*n]

;node operator+(

const node &x,

const node &y)

node operator-(

const node &x,

const node &y)

ll operator*(

const node &x,

const node &y)

node now;

ll dis

(const node &x)

bool

cmp(node x,node y)

int num,ds[

10*n]

;double ag[n*10]

;bool

cmp2

(int x,

int y)

#define nxt(k) ((k==top)?1:k+1)

#define lst(k) ((k==1)?top:k-1)

ll ans[

10*n]

;int top;

int st2[

20*n]

,st[

20*n]

;void

get(node *ar,

int num)

}node u1[n]

,u2[n]

;void

doit

(int l,

int r)

int mid=

(l+r)

>>1;

doit

(l,mid)

,doit

(mid+

1,r)

; u1[1]

=ap[mid]

;fod

(i,mid-

1,l) u1[mid-i+1]

=u1[mid-i]

+ap[i]

;get

(u1,mid-l+1)

; st2[0]

=top;

fo(i,

1,top) st2[i]

=st[i]

; u2[1]

=ap[mid+1]

;fo(i,mid+

2,r) u2[i-mid]

=u2[i-mid-1]

+ap[i]

;get

(u2,r-mid)

; st[0]

=top;

st[++st[0]

]=st[1]

,st2[

++st2[0]

]=st2[1]

;int x=

1,y=1;

while

(x||y)}

ll calc

(int mx,

int i)

intmain()

while

(calc

(mx,ds[i]

)<=0||

(calc

(mx,ds[i]

)>=0&&

calc

(lst

(mx)

,ds[i]

)>0)

) mx=

nxt(mx);

ans[ds[i]

]=ask[ds[i]

]*ar[st[mx]];

}fo(i,1

,q)printf

("%lld\n"

,ans[i]);

}

JZOJ 交換 模擬

給出字串s和字串t,現在你要把s的某乙個字元和t的某乙個字元交換,使得交換之後的s至少要有三個連續相同的字元,交換之後的t也要有三個連續相同的字元。問有多少種不同的交換方式。第一行,乙個字串s。s只含有 r g b 三種字元,長度不超過50,不小於3。而且s任意兩個相鄰的字元都不相同。第二行,乙個字...

JZOJ 規律 遊戲

有一堆金塊,king和貓老大輪流抽金塊,每次抽的個數必然是2的次方冪,求勝利 抽走最後一塊 的是誰 三行每行乙個數 n 0對於每局,如果 king 必勝則輸出一行 king will win.否則第一行輸出 maolaoda willwin.第二行輸出他第一次拿的最小數量。8 42maolaoda ...

JZOJ 禮物 數論

聖誕節這天,某商店準備了n個禮品盒,分別用整數1 n進行編號。其中,編號為1的盒子中有乙個糖果,編號為2的盒子中有2個糖果,編號為n的盒子中有n個糖果。這天一早,中山幼兒園的k個小朋友一起來到這間商店。作為當天的第一批顧客,這些小朋友可以從這n個禮品盒中選出兩個拿走。小朋友們商量了一會兒後決定,他們...