CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 树启 + 状压

传送门

文章目录

题意:

在这里插入图片描述

思路:

据说是树启的压轴题。
先观察题意,字符有 1 − 22 1-22 122中,为什么不是 1 − 26 1-26 126个?显然他就是让你状压的。我们考虑将每条路径上字符状压成 s t a t e state state,让后从 1 1 1开始遍历,记从 1 1 1 i i i的路径上的 s t a t e state state d i s [ i ] dis[i] dis[i]
再观察一下回文的性质,回文中奇数个字母最多只有一个,如果两条路径能构成回文,那么他们的 d i s [ i ]    x o r    d i s [ j ] dis[i] \ \ xor\ \ dis[j] dis[i]  xor  dis[j]最多只有 23 23 23种情况,即 00...00 , 10...00 , 01...00 , . . . , 00...01 00...00,10...00,01...00,...,00...01 00...00,10...00,01...00,...,00...01。那么我们就可以每次都 c h e c k check check一下是否存在 d i s [ j ] = d i s [ i ]    x o r    23 种 情 况 dis[j]=dis[i]\ \ xor \ \ 23种情况 dis[j]=dis[i]  xor  23。又因为每个状态有可能有多个 d e p t h depth depth,让后我就蠢的对每个状态开了个 m u l t i s e t multiset multiset,先不说内存爆没爆(我卡了下内存没爆),复杂度高达 O ( 23 n l o g 2 n ) O(23nlog^2n) O(23nlog2n)我也不知道我怎么想的,就这么写了写交了, 结局也比较显然, T L E t e x t 10 TLE text10 TLEtext10了(逃。
显然这个题可以不用 m u l t i s e t multiset multiset,记 m x [ i ] mx[i] mx[i]为状态是 i i i的最大深度,根据 d s u dsu dsu的特性,每次我们清空的时候都将 m x [ i ] mx[i] mx[i]重置为 0 0 0,每次算的时候就贪心的用 m x [ i ] mx[i] mx[i]即可。相信大部分第一反应都是这样做,但是可能考虑到直接置为 0 0 0可能会影响到重儿子导致答案错误就放弃了这种想法。那么为什么这样是正确的呢?因为 d s u dsu dsu每次清空的时候都是清空非重儿子的子树,而且是清空之后才遍历重儿子,所以不会影响到重儿子的值。还是要对 d s u dsu dsu的遍历顺序理解的比较深刻才能想到。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=500010,M=N*2,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n;
int e[M],ne[M],w[M],h[N],idx;
int depth[N],son[N],se[N],dis[N];
int ans[N],len,mx[(1<<23)];

void add(int a,int b,int c)
{
    
    
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void dfs_son(int u,int fa,int state)
{
    
    
    dis[u]=state; se[u]=1;
    depth[u]=depth[fa]+1;
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        dfs_son(x,u,state^(1<<w[i]));
        se[u]+=se[x];
        if(se[x]>se[son[u]]) son[u]=x;
    }
}

void solve(int u,int fa,int rt)
{
    
    
    int y=dis[u];
    if(mx[y]!=0) ans[rt]=max(ans[rt],depth[u]+mx[y]-2*depth[rt]);
    for(int i=0;i<22;i++)
    {
    
    
        y=dis[u]^(1<<i);
        if(mx[y]!=0) ans[rt]=max(ans[rt],depth[u]+mx[y]-2*depth[rt]);
    }
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        solve(x,u,rt);
    }
}

void update(int u,int fa,int tag)
{
    
    
    if(tag==1) mx[dis[u]]=max(mx[dis[u]],depth[u]);
    else mx[dis[u]]=0;
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        update(x,u,tag);
    }
}

void dfs(int u,int fa,int op)
{
    
    
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa||x==son[u]) continue;
        dfs(x,u,0); ans[u]=max(ans[u],ans[x]);
    }
    if(son[u]) dfs(son[u],u,1),ans[u]=max(ans[u],ans[son[u]]);
    if(son[u])
    {
    
    
        if(mx[dis[u]]) ans[u]=max(ans[u],mx[dis[u]]-depth[u]);
        for(int i=0;i<22;i++) if(mx[dis[u]^(1<<i)]) ans[u]=max(ans[u],mx[dis[u]^(1<<i)]-depth[u]);
    }
    mx[dis[u]]=max(mx[dis[u]],depth[u]);
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa||x==son[u]) continue;
        solve(x,u,u); update(x,u,1);
    }
    if(!op) update(u,fa,-1);
}

int main()
{
    
    
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d",&n);  idx=0;
    memset(h,-1,sizeof(h));
    for(int i=2;i<=n;i++)
    {
    
    
        int a; char b[2];
        scanf("%d%s",&a,b);
        add(a,i,(int)(b[0]-'a'));
    }
    dfs_son(1,0,0);
    dfs(1,0,1);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    puts("");



	return 0;
}
/*

*/



贴个 T L E TLE TLE的代码记录一下我的蜜汁操作

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=500010,M=N*2,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n;
int e[M],ne[M],w[M],h[N],idx;
int depth[N],son[N],se[N],dis[N];
int ans[N],len;
multiset<int>s[(1<<23)];

void add(int a,int b,int c)
{
    
    
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void dfs_son(int u,int fa,int state)
{
    
    
    dis[u]=state; se[u]=1;
    depth[u]=depth[fa]+1;
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        dfs_son(x,u,state^(1<<w[i]));
        se[u]+=se[x];
        if(se[x]>se[son[u]]) son[u]=x;
    }
}

void solve(int u,int fa,int rt)
{
    
    
    int y=dis[u];
    if(s[y].size()) len=max(len,depth[u]+(*s[y].rbegin())-2*depth[rt]);
    for(int i=0;i<22;i++)
    {
    
    
        y=dis[u]^(1<<i);
        if(s[y].size()) len=max(len,depth[u]+(*s[y].rbegin())-2*depth[rt]);
    }
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        solve(x,u,rt);
    }
}

void update(int u,int fa,int tag)
{
    
    
    if(tag==1) s[dis[u]].insert(depth[u]);
    else s[dis[u]].erase(s[dis[u]].find(depth[u]));
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        update(x,u,tag);
    }
}

void solve_son(int u,int fa,int rt)
{
    
    
    if((dis[u]^dis[rt])==0) len=max(len,depth[u]-depth[rt]);
    for(int i=0;i<22;i++)
    {
    
    
        int y=dis[u]^(1<<i);
        if(y!=dis[rt]) continue;
        len=max(len,depth[u]-depth[rt]);
    }
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        solve_son(x,u,rt);
    }
}

void dfs(int u,int fa,int op)
{
    
    
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa||x==son[u]) continue;
        dfs(x,u,0);
    }
    if(son[u]) dfs(son[u],u,1);
    s[dis[u]].insert(depth[u]);
    if(son[u]) solve_son(son[u],u,u);
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa||x==son[u]) continue;
        solve(x,u,u); update(x,u,1);
    }
    ans[u]=len; len=0;
    if(!op) update(u,fa,-1),len=0;
}

void dfs_ans(int u,int fa)
{
    
    
    for(int i=h[u];~i;i=ne[i])
    {
    
    
        int x=e[i];
        if(x==fa) continue;
        dfs_ans(x,u);
        ans[u]=max(ans[u],ans[x]);
    }
}

int main()
{
    
    
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d",&n);  idx=0;
    memset(h,-1,sizeof(h));
    for(int i=2;i<=n;i++)
    {
    
    
        int a; char b[2];
        scanf("%d%s",&a,b);
        add(a,i,(int)(b[0]-'a'));
    }
    dfs_son(1,0,0);
    dfs(1,0,1);
    dfs_ans(1,0);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    puts("");

















	return 0;
}
/*

*/









猜你喜欢

转载自blog.csdn.net/m0_51068403/article/details/115227038