• #树上启发式合并,trie#JZOJ 5363 生命之树


    BrNIFf.png


    分析

    考虑按位处理,
    如果熟悉dsu的话可以发现这道题能够用dsu做,
    再用两个trie分别维护该位为0或1的字符串,
    重儿子可以按照子树字符串的总长计算


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #define rr register
    using namespace std;
    const int N=100011,M=500011; typedef long lll; char s[M];
    struct node{int y,next;}e[N<<1]; lll now,ans[N],siz[N];
    int as[N],a[N],S,et=1,n,r[N],root,dep[N],fat[N],big[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(lll ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    struct Trie{
    	int tot,trie[M][26],cnt[M];
    	inline void Clear(){memset(trie[1],0,sizeof(trie[1])),cnt[tot=1]=0;}
    	inline void Insert(int L,int R){
    		rr int p=1; ++cnt[p];
    		for (rr int i=L;i<R;++i){
    			if (!trie[p][s[i]-97]){
    			    trie[p][s[i]-97]=++tot,cnt[tot]=0,
    				memset(trie[tot],0,sizeof(trie[tot]));
    			}
    			p=trie[p][s[i]-97],++cnt[p];
    		}
    	}
    	inline signed query(int L,int R){
    		rr int p=1,sum=0;
    		for (rr int i=L;i<R;++i){
    			p=trie[p][s[i]-97];
    			if (!p) return sum;
    			sum+=cnt[p];
    		}
    		return sum;
    	}
    }trie0,trie1;
    inline void dfs1(int x,int fa){
    	dep[x]=dep[fa]+1,fat[x]=fa,siz[x]=r[x]-r[x-1];
    	for (rr int i=as[x],SIZ=-1;i;i=e[i].next)
    	if (e[i].y!=fa){
    		dfs1(e[i].y,x);
    		siz[x]+=siz[e[i].y];
    		if (siz[e[i].y]>SIZ) big[x]=e[i].y,SIZ=siz[e[i].y];
    	}
    }
    inline void updqry(int x){
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (e[i].y!=fat[x]&&e[i].y!=root) updqry(e[i].y);
    	if (a[x]&S) now+=trie0.query(r[x-1],r[x]),trie1.Insert(r[x-1],r[x]);
    	    else now+=trie1.query(r[x-1],r[x]),trie0.Insert(r[x-1],r[x]);
    }
    inline void dfs2(int x,int opt){
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,0);
    	if (big[x]) dfs2(big[x],1),root=big[x];
    	updqry(x),ans[x]+=now*S,root=0;
    	if (!opt) trie0.Clear(),trie1.Clear(),now=0;
    }
    signed main(){
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
        n=iut(),trie0.tot=trie1.tot=r[0]=1;
        for (rr int i=1;i<=n;++i) a[i]=iut();
        for (rr int i=1;i<=n;++i){
        	r[i]=r[i-1]; rr char c=getchar();
        	while (!isalpha(c)) c=getchar();
        	while (isalpha(c)) s[r[i]++]=c,c=getchar();
    	}
        for (rr int i=1;i<n;++i){
        	rr int x=iut(),y=iut();
        	e[++et]=(node){y,as[x]},as[x]=et,
        	e[++et]=(node){x,as[y]},as[y]=et; 
    	}
    	dfs1(1,0); for (S=1;S<N;S<<=1) dfs2(1,0);
    	for (rr int i=1;i<=n;++i) print(ans[i]),putchar(10);
    	return 0;
    }
    
  • 相关阅读:
    深入浅出设计模式【转载】
    将EXCEL数据入ACCESS
    SFDC中的DEBUG
    2017新开始
    js获取窗体大小
    VS2005和VS2008快捷键大全
    Office云平台性能测试人员,全国火热征集中
    JQuery设置cookie|JQuery删除cookie|JQuery获取cookie 过期
    xpath操作xml
    Aptana中的中文显示乱码问题 .
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13916685.html
Copyright © 2020-2023  润新知