國際慣例的題面:
代價理解為重心和每個點這個點對的代價。根據期望的線性性,我們枚舉每個點,計算會產生的ij點對的代價即可。
那么,i到j的鏈上,i必須是第一個被選擇的點。
對于i來說,就是1/dis(i,j)。
所以答案就是sigma(i,j) 1/(dis(i,j)+1)。
然而這樣計算是n^2的,考慮優化。
如果我們能計算出邊長為某個數值的邊的數量的話,是不是就能計算答案呢?
統計路徑的題,一眼點分治。
考慮怎樣計算,我們能dfs出每個子樹中距離分治重心為x的點有多少個,然后我們枚舉兩個點讓他們取去組成路徑即可。
這顯然是個卷積,FFT優化。我們補集轉化,先計算全部方案,再減去本身對本身(兩個點來自相同子樹)的方案。
為什么這樣算復雜度正確?因為當當前分治層數一定時,所有子樹的最深點的深度總和是O(n)的,并且那個log還會更小。這樣分析的話發現復雜度是O(nlog^2n)。
正常的二元關系計算方式是前綴和和當前的卷積貢獻,為什么這次不能這樣呢?
給你一棵掃把形的樹,一半的點形成一條鏈,顯然你會選擇掃把的重心(一邊是一堆葉子,一邊是鏈)當做重心。
然后你發現鏈的那邊長度為n/2,如果你對每個葉子都和鏈做一次卷積的話,恭喜你卡成n^2logn,不如暴力......
代碼:
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<cmath>
5 const int maxn=
262145;
6 const int inf=
0x3f3f3f3f;
7 const double pi = acos(-
1.0);
8
9 int tim[maxn];
10
11 namespace FFT {
12 struct Complex {
13 double r,i;
14 friend Complex
operator + (
const Complex &a,
const Complex &b) {
return (Complex){a.r+b.r,a.i+
b.i}; }
15 friend Complex
operator - (
const Complex &a,
const Complex &b) {
return (Complex){a.r-b.r,a.i-
b.i}; }
16 friend Complex
operator * (
const Complex &a,
const Complex &b) {
return (Complex){a.r*b.r-a.i*b.i,a.r*b.i+a.i*
b.r}; }
17 }cp[maxn];
18 inline
void FFT(Complex* dst,
int n,
int tpe) {
19 for(
int i=
0,j=
0;i<n;i++
) {
20 if( i <
j ) std::swap(dst[i],dst[j]);
21 for(
int t=n>>
1;(j^=t)<t;t>>=
1) ;
22 }
23 for(
int len=
2;len<=n;len<<=
1) {
24 const int h = len >>
1;
25 const Complex per = (Complex){cos(pi*tpe/h),sin(pi*tpe/
h)};
26 for(
int st=
0;st<n;st+=
len) {
27 Complex w = (Complex){
1.0,
0.0};
28 for(
int pos=
0;pos<h;pos++
) {
29 const Complex u = dst[st+pos] , v = dst[st+pos+h] *
w;
30 dst[st+pos] = u + v , dst[st+pos+h] = u - v , w = w *
per;
31 }
32 }
33 }
34 if( !~tpe )
for(
int i=
0;i<n;i++) dst[i].r /=
n;
35 }
36 inline
void mul(
int* dst,
int n) {
37 int len =
1;
38 while( len <= ( n <<
1 ) ) len <<=
1;
39 for(
int i=
0;i<len;i++) cp[i] = (Complex){(
double)dst[i],
0.0};
40 FFT(cp,len,
1);
41 for(
int i=
0;i<len;i++) cp[i] = cp[i] *
cp[i];
42 FFT(cp,len,-
1);
43 for(
int i=
0;i<len;i++) dst[i] = (
int)(cp[i].r+
0.5);
44 }
45 }
46
47 namespace Tree {
48 int s[maxn],t[maxn<<
1],nxt[maxn<<
1];
49 int siz[maxn],mxs[maxn],ban[maxn];
50 int su[maxn],tp[maxn];
51
52 inline
void addedge(
int from,
int to) {
53 static int cnt =
0;
54 t[++cnt] = to , nxt[cnt] = s[
from] , s[
from] =
cnt;
55 }
56 inline
void findroot(
int pos,
int fa,
const int &fs,
int &
rt) {
57 siz[pos] =
1 , mxs[pos] =
0;
58 for(
int at=s[pos];at;at=nxt[at])
if( t[at] != fa && !ban[t[at]] ) findroot(t[at],pos,fs,rt) , siz[pos] += siz[t[at]] , mxs[pos] =
std::max( mxs[pos] , siz[t[at]] );
59 if( ( mxs[pos] = std::max( mxs[pos] , fs - siz[pos]) ) <= mxs[rt] ) rt =
pos;
60 }
61 inline
void dfs(
int pos,
int fa,
int dep,
int &
mxd) {
62 mxd = std::max( mxd , dep ) , ++
tp[dep];
63 for(
int at=s[pos];at;at=nxt[at])
if( t[at] != fa && !ban[t[at]] ) dfs(t[at],pos,dep+
1,mxd);
64 }
65 inline
void solve(
int pos,
int fs) {
66 int root =
0 , mxd =
0 , ths ;
67 *mxs = inf, findroot(pos,-
1,fs,root) , ban[root] =
1;
68 for(
int at=s[root];at;at=nxt[at])
if( !
ban[t[at]]) {
69 ths =
0 , dfs(t[at],root,
1,ths) , mxd =
std::max( mxd , ths );
70 for(
int i=
1;i<=ths;i++) su[i] +=
tp[i];
71 FFT::mul(tp,ths);
72 for(
int i=
1;i<=ths<<
1;i++) tim[i] -=
tp[i];
73 memset(tp,
0,
sizeof(
int)*(ths<<
1|
1));
74 }
75 ++*
su , FFT::mul(su,mxd);
76 for(
int i=
1;i<=mxd<<
1;i++) tim[i] +=
su[i];
77 memset(su,
0,
sizeof(
int)*(mxd<<
1|
1));
78 for(
int at=s[root];at;at=nxt[at])
if( !ban[t[at]] ) solve(t[at],siz[t[at]]<siz[root]?siz[t[at]]:fs-
siz[root]);
79 }
80 }
81
82 int main() {
83 static int n;
84 static long double ans;
85 scanf(
"%d",&
n);
86 for(
int i=
1,a,b;i<n;i++) scanf(
"%d%d",&a,&b) , ++a , ++
b , Tree::addedge(a,b) , Tree::addedge(b,a);
87 Tree::solve(
1,n) , ans =
n;
88 for(
int i=
1;i<=n<<
1;i++) ans += (
long double) tim[i] / ( i +
1 );
89 printf(
"%0.4Lf\n",ans);
90 return 0;
91 }
View Code
ここでこのまま
即使在這里就這樣
僕が消えてしまっても 誰も知らずに
我消失不見了 誰也不會知道吧
明日が來るのだろう
明天依然會來臨吧
わずか 世界のひとかけらに過ぎない
我僅僅是 這個世界的微小碎屑
ひとりを夜が包む
夜晚懷抱孤獨的身影
轉載于:https://www.cnblogs.com/Cmd2001/p/8969717.html
總結
以上是生活随笔為你收集整理的3451: Tyvj1953 Normal 点分治 FFT的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。