2023秋季综合训练(三)

问题 G: 夜刀与黑角
如果两个人全部访问则 ans = 4*(n-1)
考虑删除没有遍历的节点

对于角色A:
1.对于以u为根的节点,如果存在A需要访问的节点,则u必须要访问
2.对于以u为根的节点,如果存在B需要访问的节点x,dep[x]-dep[u]>=D,则u须要访问
3.其他情况,可以不用访问

dfs求每个节点是否需要访问,如果不需要则-2(一来一回)

点击查看代码
const int N=2e5+10;
vector<int> g[200010];
int n,D,ans;
//d1[u],A角色以u为根节点要到达的最远距离(深度)
int k1[N],k2[N],d[N],d1[N],d2[N];
void dfs(int u,int fa){
    //标记访问深度
    if(k1[u]) d1[u]=d[u];
    if(k2[u]) d2[u]=d[u];
    for(int v:g[u]){
        if(v==fa) continue;
        d[v]=d[u]+1;
        dfs(v,u);
        d1[u]=max(d1[u],d1[v]);
        d2[u]=max(d2[u],d2[v]);
    }
    if(u==1) return;
    //以u为根的子树A角色不用访问,则不用访问
    if(!d1[u]&&d2[u]-d[u]<D) ans-=2;//来回-2
    //同理
    if(!d2[u]&&d1[u]-d[u]<D) ans-=2;

}

void bu_f(){
    n=read(),D=read();   
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        g[x].push_back(y);
        g[y].push_back(x);
    }
    //假设全部点都要遍历
    ans=4*(n-1);
    int m1=read();
    for(int i=1;i<=m1;i++){
        int x=read();
        k1[x]=1;
    }
    int m2=read();
    for(int i=1;i<=m2;i++){
        int x=read();
        k2[x]=1;
    }
    d[1]=1;
    //删掉不用遍历的点
    dfs(1,0);
    write(ans);
}

问题 I: Bessie看Mooloo

考虑d[i]到d[i+1]天转移要么是k+1,要么是d[i+1]-d[i],两则取最小即可

点击查看代码
LL a[100010];
LL ans,n,k;
void bu_f(){
    n=read(),k=read();
    for(int i=1;i<=n;i++) a[i]=read();
    ans=k+1;
    for(int i=2;i<=n;i++) {
        ans+=min(k+1,a[i]-a[i-1]);
    }
    cout<<ans;
}
posted @ 2023-11-19 20:23  不o凡  阅读(11)  评论(0)    收藏  举报