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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【CodeForces】914 E. Palindromes in a Tree 点分治

發布時間:2025/3/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CodeForces】914 E. Palindromes in a Tree 点分治 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目】E. Palindromes in a Tree

【題意】給定一棵樹,每個點都有一個a~t的字符,一條路徑回文定義為路徑上的字符存在一個排列構成回文串,求經過每個點的回文路徑數。n<=2*10^5。

【算法】點分治

【題解】狀壓20位的二進制表示一條路徑的字符狀態,點分治過程中維護掃描過的路徑只須維護狀態桶數組,t[i]表示前面狀態為i的路徑條數。

合并:考慮當前狀態為j,要使合并的狀態滿足條件即i^j=1<<k(0<=k<20)或i^j=0,移項得i=j^(1<<k)或i=j,所以路徑數是Σ t [ j^(1<<k) ]+t[j]。

統計每個點:對于當前要處理的重心x,先遍歷所有子樹得到整個t[]數組,然后對每個子樹先刪除其在桶里的狀態,然后掃一遍貢獻子樹中每個點,最后將子樹的狀態加回桶中。

這樣可以做到每條路徑都貢獻到每個點,要特殊處理重心的貢獻。

復雜度O(n log n)。

#include<cstdio> #include<cctype> #include<algorithm> #define ll long long using namespace std; const int maxn=200010,maxN=2000010; int tot,first[maxn],sz[maxn],vis[maxn],sum,root,a[maxn],u,v,n; ll ans[maxn],t[maxN]; struct edge{int v,from;}e[maxn*2];void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;} void getroot(int x,int fa){sz[x]=1;bool ok=1;for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v]){getroot(e[i].v,x);sz[x]+=sz[e[i].v];if(sz[e[i].v]>sum/2)ok=0;}if(ok&&sz[x]>=sum/2)root=x; } void dfs(int x,int fa,int p,int s){t[s^=(1<<a[x])]+=p;for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])dfs(e[i].v,x,p,s); } ll calc(int x,int fa,int s){s^=(1<<a[x]);ll num=t[s];for(int i=0;i<20;i++)num+=t[s^(1<<i)];for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])num+=calc(e[i].v,x,s);ans[x]+=num;return num; } void solve(int x,int s){vis[x]=1;dfs(x,0,1,0);ll num=t[0];for(int i=0;i<20;i++)num+=t[1<<i];for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){dfs(e[i].v,x,-1,1<<a[x]);num+=calc(e[i].v,x,0);dfs(e[i].v,x,1,1<<a[x]);}ans[x]+=num/2;dfs(x,0,-1,0);for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){if(sz[e[i].v]>sz[x])sum=s-sz[x];else sum=sz[e[i].v];getroot(e[i].v,x);solve(root,sum);} } char s[maxn]; int main(){scanf("%d",&n);for(int i=1;i<n;i++){scanf("%d%d",&u,&v);insert(u,v);insert(v,u);}scanf("%s",s+1);for(int i=1;i<=n;i++)a[i]=s[i]-'a';sum=n;getroot(1,0);solve(root,sum);for(int i=1;i<=n;i++)printf("%lld ",ans[i]+1);return 0; } View Code

?

轉載于:https://www.cnblogs.com/onioncyc/p/8334111.html

總結

以上是生活随笔為你收集整理的【CodeForces】914 E. Palindromes in a Tree 点分治的全部內容,希望文章能夠幫你解決所遇到的問題。

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