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");
            }
        }
    }
}
 

 

上一篇:SP375 QTREE - Query on a tree


下一篇:2020 CSP-S2 & NOIP 2020 考试小错误总结