zoukankan      html  css  js  c++  java
  • [CF741D]Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    luogu

    Description

    一棵以(1)号点为根的有根树,每条边上有一个小写字母(a~v)。定义一条路经是好的,当且仅当这条路径上经过的所有小写字母重排后可以构成回文串。
    求以每个点为根的子树中最长的好的路径。

    sol

    算法发明者自己出的题,可以去他的blog里面看看。

    首先,对于一条字母是(ch)的边,定义其权值为(2^{ch-'a'})
    这样一条路经是好的就当且仅当这条路径的异或和二进制位中的(1)的个数不超过(1)
    在处理以某一点为根的子树时,开桶,记(f[i])表示到根路径异或和为(i)的点的最大深度,可以类似点分的方法计算答案并更新桶。
    现在问题的瓶颈在于:每棵子树需要分别处理,把结果全部保存下来空间开不下,而每次重新计算一遍时间上吃不消。
    考虑(dsu on tree)
    先递归处理轻儿子,删除轻儿子的贡献,递归处理重儿子,保存其贡献,再把轻儿子全部再算一遍。
    复杂度是(O(nlog n))的。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 5e5+5;
    int n,nxt[N],val[N],head[N],dfn[N],low[N],tim,id[N],dep[N],sz[N],son[N],Xor[N],f[1<<22],ans[N];
    void dfs1(int u){
    	id[dfn[u]=++tim]=u;sz[u]=1;
    	for (int v=head[u];v;v=nxt[v]){
    		dep[v]=dep[u]+1;Xor[v]=Xor[u]^val[v];
    		dfs1(v);sz[u]+=sz[v];
    		if (sz[v]>sz[son[u]]) son[u]=v;
    	}
    	low[u]=tim;
    }
    void dfs(int u,int keep){
    	for (int v=head[u];v;v=nxt[v])
    		if (v!=son[u]) dfs(v,0),ans[u]=max(ans[u],ans[v]);
    	if (son[u]) dfs(son[u],1),ans[u]=max(ans[u],ans[son[u]]);
    
    	if (f[Xor[u]]) ans[u]=max(ans[u],f[Xor[u]]-dep[u]);
    	for (int i=0;i<22;++i)
    		if (f[Xor[u]^(1<<i)]) ans[u]=max(ans[u],f[Xor[u]^(1<<i)]-dep[u]);
    	f[Xor[u]]=max(f[Xor[u]],dep[u]);
    
    	for (int v=head[u];v;v=nxt[v])
    		if (v!=son[u]){
    			for (int i=dfn[v];i<=low[v];++i){
    				if (f[Xor[id[i]]]) ans[u]=max(ans[u],f[Xor[id[i]]]+dep[id[i]]-(dep[u]<<1));
    				for (int j=0;j<22;++j)
    					if (f[Xor[id[i]]^(1<<j)])
    						ans[u]=max(ans[u],f[Xor[id[i]]^(1<<j)]+dep[id[i]]-(dep[u]<<1));
    			}
    			for (int i=dfn[v];i<=low[v];++i){
    				f[Xor[id[i]]]=max(f[Xor[id[i]]],dep[id[i]]);
    			}
    		}
    	if (!keep) for (int i=dfn[u];i<=low[u];++i) f[Xor[id[i]]]=0;
    }
    int main(){
    	n=gi();
    	for (int i=2;i<=n;++i){
    		int f=gi();char ch=getchar();
    		nxt[i]=head[f];val[i]=1<<ch-'a';head[f]=i;
    	}
    	dep[1]=1;dfs1(1);dfs(1,0);
    	for (int i=1;i<=n;++i) printf("%d ",ans[i]);
    	puts("");return 0;
    }
    
  • 相关阅读:
    ArcGIS API中FindTask中文搜索无效,服务器编码问题URIEncoding="utf-8"
    ArcGIS10.1 api for Flex开发用于ArcGIS 9.3时QueryTask 'Error #2032'错误的解决方案
    Arcgis API For IOS扩展AGSDynamicLayer新旧版API对比
    谈FME批量自动化数据转换方法
    浅谈城市规划在移动GIS方面的应用发展
    JS-JQuery(JSONP)调用WebService跨域若干技术点
    CAD规划成果入库GIS_SDE转换之分析
    Web前台直接加载GIS格式数据分析
    [转] 基于ArcGISServer实现活动地图标注
    程序员如何利用空闲时间挣零花钱
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9116039.html
Copyright © 2011-2022 走看看