1. 程式人生 > >Codeforces 600E Lomsat gelral(dsu on tree)

Codeforces 600E Lomsat gelral(dsu on tree)

  dsu on tree板子題。這個trick保證均攤O(nlogn)的複雜度,要求資瓷O(1)將一個元素插入集合,清空集合時每個元素O(1)刪除。(當然log的話就變成log^2了)

  具體的,每次先遍歷輕兒子的子樹,暴力求得所需資訊,每遍歷完一棵輕子樹都將其資訊清空。然後遍歷重子樹,暴力求得所需資訊,保留資訊,再重新遍歷輕子樹將資訊合併,最後加上根本身得到原子樹的資訊。

  複雜度證明考慮每個點的資訊被統計的次數,顯然這隻與其到根的路徑上輕邊條數有關,於是複雜度O(nlogn)。

#include<iostream> 
#include<cstdio>
#include
<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 100010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int
m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[N],p[N],fa[N],size[N],son[N],cnt[N],mx,t; ll ans[N],cur;
struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void make(int k) { size[k]=1; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) { fa[edge[i].to]=k; make(edge[i].to); size[k]+=size[edge[i].to]; if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to; } } void update(int x,int op) { cnt[x]+=op; if (op==1) { if (cnt[x]>mx) mx=cnt[x],cur=0; if (cnt[x]>=mx) cur+=x; } else mx=cur=0; } void add(int k,int op) { update(a[k],op); for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) add(edge[i].to,op); } void dfs(int k) { for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) dfs(edge[i].to),add(edge[i].to,-1); if (son[k]) dfs(son[k]); for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) add(edge[i].to,1); update(a[k],1);ans[k]=cur; } int main() { #ifndef ONLINE_JUDGE freopen("600E.in","r",stdin); freopen("600E.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); } make(1); dfs(1); for (int i=1;i<=n;i++) printf("%I64d ",ans[i]); return 0; }