1481F.AB Tree(树上信息统计+01背包+记录DP路径+Bitset优化时间复杂度)
作者:互联网
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; const int inf=1e9; int n,m,x; int dep[maxn];//节点在第几层 int num[maxn];//每一层的节点个数 int lev[maxn];//每一层的叶子节点个数 bitset<maxn> f[2500]; int w[maxn]; int ok[maxn]; vector<int> g[maxn],v[maxn]; unordered_map<int,int> vis; void dfs1 (int x,int pre) { dep[x]=dep[pre]+1; num[dep[x]]++; m=max(m,dep[x]); if (g[x].size()==1) lev[dep[x]]++; for (int y:g[x]) { if (y==pre) continue; dfs1(y,x); } } void dfs2 (int x,int y) { //找dp状态 if (x==0) return; for (int i=0;i<v[x].size();i++) { if (w[x]>y||f[x-1][y]) break; y-=w[x]; ok[v[x][i]]=1; } dfs2(x-1,y); } int main () { scanf("%d%d",&n,&x); for (int i=2;i<=n;i++) { int y; scanf("%d",&y); g[i].push_back(y); g[y].push_back(i); } dfs1(1,0); int cnt=0; for (int i=1;i<=m;i++) { //第一步,把相同点数的层合并 //由于树的性质,合并后的层数不会超过sqrt(n),这是第一步优化 if (vis[num[i]]) { v[vis[num[i]]].push_back(i); } else { vis[num[i]]=++cnt; w[cnt]=num[i]; v[cnt].push_back(i); } } f[0][0]=1; for (int i=1;i<=cnt;i++) { f[i]=f[i-1]; int sz=v[i].size(); for (int j=1;j<=sz;j<<=1) { sz-=j; f[i]|=(f[i]<<(j*w[i])); } if (sz) f[i]|=f[i]<<(sz*w[i]);//这一步还没懂 } if (f[cnt][x]) { printf("%d\n",m); dfs2(cnt,x); for (int i=1;i<=n;i++) { if (ok[dep[i]]) printf("a"); else printf("b"); } } else { int ans=inf; for (int i=x;i>=0;i--) if (f[cnt][i]) { ans=i; break; } dfs2(cnt,ans); int pp=-1; for (int i=1;i<=m;i++) { if (!ok[i]&&lev[i]>=x-ans) { pp=i; break; } } printf("%d\n",m+1); for (int i=1;i<=n;i++) { if (dep[i]==pp&&g[i].size()==1) { if (ans==x) printf("b"); else printf("a"),ans++; } else { if (ok[dep[i]]) printf("a"); else printf("b"); } } } }
标签:pre,1481F,AB,dfs2,int,复杂度,dep,maxn,ans 来源: https://www.cnblogs.com/zhanglichen/p/14395945.html