日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3451: Tyvj1953 Normal 点分治 FFT

發布時間:2025/4/14 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3451: Tyvj1953 Normal 点分治 FFT 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

國際慣例的題面:

代價理解為重心和每個點這個點對的代價。根據期望的線性性,我們枚舉每個點,計算會產生的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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。