G - Game on Tree 2(主席树+树形dp)

该博客介绍了如何结合主席树和树形动态规划来解决寻找树结构中中位数的问题。首先,通过主席树计算从根节点到叶子节点的树链中位数,然后依据中位数进行树形DP。当深度为奇数时,Alice选择最大中位数;为偶数时,Bob选择最小中位数。博主提供了详细的代码实现,并进行了深度优先搜索(DFS)来完成这个任务。
摘要由CSDN通过智能技术生成

G - Game on Tree 2(主席树+树形dp)

传送门

思路:

首先中位数为跟到叶子节点的树链的中位数, 我们能用主席树算出,然后根据中位数来树形dp,深度为奇数则是Alice操作选中位数最大,偶数为BOb操作选中位数最小。

代码
#include <iostream>
#include <vector>
#include <algorithm>
#define mid (l+r>>1)
using namespace std;
const int N=1e5+7;
int n,tot,a[N],rt[N],f[N];
struct node{int lc,rc,v;}tr[40*N];
vector <int> G[N],ho;
int get(int x){return lower_bound(ho.begin(),ho.end(),x)-ho.begin()+1;}
void insert(int &k,int pr,int l,int r,int p){
    k=++tot;tr[k]=tr[pr],tr[k].v++;
    if(l==r) return;
    if(p<=mid) insert(tr[k].lc,tr[pr].lc,l,mid,p);
    else insert(tr[k].rc,tr[pr].rc,mid+1,r,p);
}
int ask(int k,int l,int r,int key){
    if(l==r) return l;
    int tem=tr[tr[k].lc].v;
    if(tem>=key) return ask(tr[k].lc,l,mid,key);
    else return ask(tr[k].rc,mid+1,r,key-tem);
}
void dfs(int p,int fa,int dep){
    insert(rt[p],rt[fa],1,n,get(a[p]));
    int ok=1;
    if(dep&1) f[p]=0;
    else f[p]=1e9;
    for(auto v:G[p]){
        if(v==fa) continue;
        dfs(v,p,dep+1);
        ok=0;
        if(dep&1){
            f[p]=max(f[p],f[v]);
        }else{
            f[p]=min(f[p],f[v]);
        }
    }
    if(ok){
        if(dep&1){
            f[p]=ho[ask(rt[p],1,n,(dep+1)/2)-1];
        }else{
            f[p]=(ho[ask(rt[p],1,n,(dep+1)/2)-1]+ho[ask(rt[p],1,n,(dep+1)/2+1)-1])/2;
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        ho.push_back(a[i]);
    }
    for(int i=1;i<=n-1;i++){
        int u,v;
        scanf("%d %d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    ho.erase(unique(ho.begin(),ho.end()),ho.end());
    sort(ho.begin(),ho.end());
    dfs(1,0,1);
    printf("%d\n",f[1]);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值