牛客算法周练——小H和游戏(树上dfs+数组优化)

题目链接


在这里插入图片描述
1.题目大意:给出一棵树,现在如果对一个节点轰炸一次,那么和它距离不超过2的节点也会被波及。现在有q(q<=7e5)次轰炸,问每次被轰炸的后此次轰炸的节点目前为止被轰炸多少次

2.很明显想到暴力dfs,但是如果只有树的深度只有2层而且所有子节点均连接在根节点,轰炸Q次根节点,时间复杂度达到了O(n2)。必须想其他方法,不难发现对于树上的某个点,我们只需要考虑它的儿子,孙子,父亲,兄弟,爷爷这五个相关节点,对树dfs后,首先肯定能求出所有节点的父节点,设ans[i][j](j=0,1,2),其中0代表该节点本身的影响,1代表它对儿子的影响,2代表它对孙子的影响。因为每个节点的父节点确定,那么我们每次轰炸一个节点后,更新它对儿子和孙子的影响,更新它对父亲以及父亲的兄弟的影响,更新它对爷爷的影响,那么:
总影响=本身的影响+其父节点对儿子的影响+其祖父节点对孙子的影响

在这里插入图片描述
3.为什么不考虑儿子和孙子对它的影响?因为儿子和孙子对它的影响已经计算在它本身影响中。为什么增加轰炸后它本身的影响?因为我们一旦增加了父亲对儿子的影响,它本身也作为父亲的儿子被更新

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=8e5+10;
vector<int> G[maxn];
int ans[maxn][3];
int fa[maxn];


void dfs(int u,int v){
    fa[v]=u;
    for(int i=0;i<G[v].size();i++){
        if(G[v][i]!=u) dfs(v,G[v][i]);
    }
}


int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n,q,a,b,x;
    cin>>n>>q;
    for(int i=1;i<n;i++) {
        cin>>a>>b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(0,1);
    while(q--) {
        cin>>x;
        ans[x][1]++;  //儿子
        ans[x][2]++;  //儿子的儿子
        ans[fa[x]][0]++;  //父亲
        ans[fa[x]][1]++;  //父亲的儿子——兄弟 (包括它自己!)
        ans[fa[fa[x]]][0]++;  //父亲的父亲
        cout<<ans[x][0]+ans[fa[x]][1]+ans[fa[fa[x]]][2]<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值