传送门
文章目录
- 题意:
- 思路:
题意:
思路:
据说是树启的压轴题。
先观察题意,字符有1−221-221−22中,为什么不是1−261-261−26个?显然他就是让你状压的。我们考虑将每条路径上字符状压成statestatestate,让后从111开始遍历,记从111到iii的路径上的statestatestate为dis[i]dis[i]dis[i]。
再观察一下回文的性质,回文中奇数个字母最多只有一个,如果两条路径能构成回文,那么他们的dis[i]xordis[j]dis[i] \ \ xor\ \ dis[j]dis[i] xor dis[j]最多只有232323种情况,即00...00,10...00,01...00,...,00...0100...00,10...00,01...00,...,00...0100...00,10...00,01...00,...,00...01。那么我们就可以每次都checkcheckcheck一下是否存在dis[j]=dis[i]xor23种情况dis[j]=dis[i]\ \ xor \ \ 23种情况dis[j]=dis[i] xor 23种情况。又因为每个状态有可能有多个depthdepthdepth,让后我就蠢的对每个状态开了个multisetmultisetmultiset,先不说内存爆没爆(我卡了下内存没爆),复杂度高达O(23nlog2n)O(23nlog^2n)O(23nlog2n),我也不知道我怎么想的,就这么写了写交了, 结局也比较显然,TLEtext10TLE text10TLEtext10了(逃。
显然这个题可以不用multisetmultisetmultiset,记mx[i]mx[i]mx[i]为状态是iii的最大深度,根据dsudsudsu的特性,每次我们清空的时候都将mx[i]mx[i]mx[i]重置为000,每次算的时候就贪心的用mx[i]mx[i]mx[i]即可。相信大部分第一反应都是这样做,但是可能考虑到直接置为000可能会影响到重儿子导致答案错误就放弃了这种想法。那么为什么这样是正确的呢?因为dsudsudsu每次清空的时候都是清空非重儿子的子树,而且是清空之后才遍历重儿子,所以不会影响到重儿子的值。还是要对dsudsudsu的遍历顺序理解的比较深刻才能想到。
//#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;
}
/**/
贴个TLETLETLE的代码记录一下我的蜜汁操作
//#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;
}
/**/