• #树链剖分,树上启发式合并#CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths


    题目


    分析

    考虑回文串当且仅当最多有一个字母出现奇数次,
    可以记录某个二进制状态的最大深度,
    一种就是点(x)到某个点,另一种就是经过点(x)的一条路径
    (x)的子树中递归实现,重儿子保留,轻儿子将标记清空,
    这样时间复杂度可以做到(O(nlog^2n))


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=500011;
    struct node{int y,w,next;}e[N];
    int k=1,son[N],ans[N],as[N],c[4200011],tt;
    int now,dep[N],fat[N],big[N],dis[N],n;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isalnum(c)) c=getchar();
    	while (isalnum(c)) ans=ans*10+c-48,c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline signed max(int a,int b){return a>b?a:b;}
    inline void add(int x,int y,int w){e[++k]=(node){y,w,as[x]},as[x]=k;}
    inline void dfs1(int x,int fa){
    	dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
    	for (rr int i=as[x],mson=-1;i;i=e[i].next)
    	if (e[i].y!=fa){
    		dis[e[i].y]=dis[x]^(1<<e[i].w);
    		dfs1(e[i].y,x),son[x]+=son[e[i].y];
    		if (son[e[i].y]>mson)
    		    big[x]=e[i].y,mson=son[e[i].y];
    	}
    }
    inline void calc(int x){
    	if (c[dis[x]]) now=max(now,dep[x]+c[dis[x]]-tt);
    	for (rr int i=0;i<22;++i) if (c[dis[x]^(1<<i)])
    	    now=max(now,dep[x]+c[dis[x]^(1<<i)]-tt);
    }
    inline void update(int x,int z){
    	if (z==1) c[dis[x]]=max(c[dis[x]],dep[x]);
    	else if (!z) calc(x); else c[dis[x]]=0;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fat[x]) update(e[i].y,z);
    }
    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); tt=dep[x]<<1;
    	for (rr int i=as[x];i;i=e[i].next)
    	    now=max(now,ans[e[i].y]);
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (e[i].y!=big[x]) update(e[i].y,0),update(e[i].y,1);//统计答案并添加深度
    	calc(x),c[dis[x]]=max(c[dis[x]],dep[x]),ans[x]=now;//更新该点
    	if (!opt) update(x,-1),now=0;//如果是轻儿子撤销标记
    }
    signed main(){
    	n=iut();
    	for (rr int i=2;i<=n;++i){
    		rr int x=iut(),w=iut()-49;
    		add(x,i,w);
    	}
    	dfs1(1,0),dfs2(1,1);
    	for (rr int i=1;i<=n;++i)
    	    print(ans[i]),putchar(32);
    	return 0;
    }
    
  • 相关阅读:
    关于php,python,javascript文件或者模块导入引入的区别和联系
    es6在网页中模块引入的方法
    pip3 升级失败的解决方法!亲测有效
    php 简单的学习GD库绘制图片并传回给前端实现方式
    session与cookie的区别以及HTML5中WebStorage理解
    二次开发项目集合
    php微信公众号开发入门小教程
    安装运行mariadb时错误:gtid_slave_pos
    发测试 HTML/FILE/MYSQL/动态 20151120
    百度浏览器 自动弹窗!
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13532251.html
Copyright © 2020-2023  润新知