[Explanations] Lomsat gelral [CF600E]

[Explanations] Lomsat gelral [CF600E]

[Introduction]

Finished \ (\ text {Dsu on tree } \) after roughly a solution to a problem browsing the Internet, a common practice are the following:

  • \ (\ text {Dsu ON Tree} \) (the majority, after all, is the board)

  • Segment tree merger (huge space)

  • \ (O (n \ sqrt { n} logn) \) a \ (\ text {DFS} \ ) sequence \ (+ \) \ (SB \) violent Mo Force (great time)

  • \ (O (n \ sqrt { n}) \) a \ (\ text {DFS} \ ) sequence \ (+ \) rollback Mo Force (average efficiency)

But they did not find a \ (\ text {DFS} \ ) sequence \ (+ \) divide and conquer, let me do it the first piece of the whole network (But I did not find, I hope it do not make up their faces)。

【analysis】

After the sub-tree to a query sequence which is essentially a series of range queries, we know that in order to use divide and conquer is the need to meet certain monotony, then these intervals whether the nature of what we want it?

First some definitions:

  • \ (size (x) \) represents \ (| subtree (the X-) | \) , ie \ (x \) is the size of the sub-tree root.

  • \ (dfn (x) \) indicate nodes \ (X \) a \ (\ text {DFS} \ ) sequence.

  • \ (idx (i) \) represents \ (\ text {DFS} \ ) sequence \ (I \) corresponding to the node number, satisfying \ (dfn (idx (i) ) = i, \ idx (dfn (x) ) = the X-\) .

  • \ (Rdfn (i) \) represents \ (I + size (IDX (I)) -. 1 \) , i.e., \ (\ text {DFS} \ ) sequence \ (I \) node in the subtree corresponding to the maximum the \ (\ text {DFS} \ ) sequence.

【lemma】

Parabolic Conclusion :
set \ (I '<I \) , if there is a \ (J \) satisfies \ (i \ leqslant j \ leqslant Rdfn (i) \) and \ (i' \ leqslant j \ leqslant Rdfn (i ' ) \) , then there must be \ (RDFN (I ') \ geqslant RDFN (I) \) .
(According to \ (\ text {YudeS} \ ) Die giant guy said through \ (J \) section contains related to each other, that is, in the interval where \ ([i, Rdfn (i )] \ ) is included in \ ([i ', Rdfn ( i')] \) in).

Actually very simple, a little think about will understand.

Demonstrate :
seen from the two conditions given \ (idx (j) \ in subtree (idx (i)) \) and \ (IDX (J) \ in subtree (IDX (I ')) \) , so \ ( idx (i), idx (i ') \) are \ (idx (j) \) of the ancestor node.
And because \ (I '<I \) , and any node \ (X \) in all its ancestors are from the root to the (X \) \ on simple path, \ (idx (i') \ ) should be \ (idx (i) \) of the ancestor node, so there is \ (RDFN (I ') \ geqslant RDFN (I) \) .

[Algorithm]

Back to this question, with the above properties, it is clear that a partition has a bar, one for \ ((L, mid, R ) \) swept again calculated: meet \ (L \ leqslant i \ leqslant mid \) and \ (mid + 1 \ leqslant Rdfn (i) \ leqslant R \) all \ (ANS [I] \) .

The time complexity is: \ (O (nlogn) \) .

Core operations on a partition function and wanted to write good, no one actually use ....

Like this \ (dot \) of the title should be able to use \ (\ text {DFS} \ ) sequence \ (+ \) rollback Mo Team / partition to engage in it, \ (INSERT \) functions do not need to change, time complexity and essentially the same partition (Konjac blind Hu mouth, credibility is very low

【Code】

#include<algorithm>
#include<cstring>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=1e5+3;
int o,n,m,x,y,t,tmp,dfn_O,A[N],Q[N],cnt[N],dfn[N],idx[N],size[N],head[N];LL ans,Ans[N];
struct QAQ{int to,next;}a[N<<1];
inline void add(Re x,Re y){a[++o].to=y,a[o].next=head[x],head[x]=o;}
inline void in(Re &x){
    int f=0;x=0;char c=getchar();
    while(c<'0'||c>'9')f|=c=='-',c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x=f?-x:x;
}
inline void dfs(Re x,Re fa){//预处理dfn序
    idx[dfn[x]=++dfn_O]=x,size[x]=1;
    for(Re i=head[x],to;i;i=a[i].next)
        if((to=a[i].to)!=fa)dfs(to,x),size[x]+=size[to];
}
inline void CL(){//清空贡献,从zero开始
    while(t)cnt[Q[t--]]=0;ans=tmp=0;
}
inline void insert(Re x){//加入点x的贡献
    ++cnt[Q[++t]=A[x]];
    if(cnt[A[x]]>tmp)tmp=cnt[ans=A[x]];
    else if(cnt[A[x]]==tmp)ans+=A[x];
}
inline void sakura(Re L,Re R){//分治解决(L,R)
    if(L==R){if(size[L]==1)Ans[L]=A[L];return;}
    Re mid=L+R>>1;
    sakura(L,mid),sakura(mid+1,R);//递归解决下面的
    Re p=mid;CL();//搞一个指针p
    for(Re i=mid,j;i>=L&&(j=i+size[idx[i]]-1)<=R;--i){//当j=Rdfn(i)大于R时就可以结束了
        insert(idx[i]);
        if(j<=mid)continue;//只解决对于j>mid的部分
        while(p<j)insert(idx[++p]);//由性质可知满足大于mid的那部分j是单调递增的,不断移动指针p即可
        Ans[idx[i]]=ans;//获得答案
    }
}
int main(){
//  freopen("123.txt","r",stdin);
    in(n),m=n-1;
    for(Re i=1;i<=n;++i)in(A[i]);
    while(m--)in(x),in(y),add(x,y),add(y,x);
    dfs(1,0),sakura(1,n);
    for(Re i=1;i<=n;++i)printf("%lld ",Ans[i]);
}

[References]

Guess you like

Origin www.cnblogs.com/Xing-Ling/p/12336327.html