zoukankan      html  css  js  c++  java
  • CF.739B 【Alyona and a tree】(倍增+树上差分/二分树上差分)

    题目链接:https://codeforces.com/contest/739/problem/B

    题意:一棵根节点为1的树,每个点都有点值a[i],每条边也有权值,dist(v, u)表示从v到u边权和,当u时v的子孙并且dist(v, u)<=a[u]时u就受v控制,输出每个结点能控制的结点数。

    解法1:倍增+树上差分

    一开始不知道该怎么去写这个树上差分,后来看了别人的题解报告算是明白了。一开始就是简单的倍增,同时求出每个点x到1的距离,即d[x]=dis(1,x)。完成第一步dfs之后,就是把当前点x不断向上跳,比如跳到y了,dis(x,y)=d[x]-d[y]刚好<a[x],那么也就是说x~y里面所有的点(除去x)都可以控制x,那么就把y的父亲差分数组-1,x的父亲差分数组+1即可。

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=2e5+5;
    int tot,head[maxn];
    struct E{
        int to,next,w;
    }edge[maxn<<1];
    void add(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,a[maxn];
    int fa[maxn][40],vis[maxn],depth[maxn],d[maxn];
    void dfs(int x,int step){
        depth[x]=step;vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(vis[v]) continue;
            fa[v][0]=x;
            d[v]=d[x]+edge[i].w;
            dfs(v,step+1);
        }
    }
    void bz(){
        for(int j=1;j<=30;j++){
            for(int i=1;i<=n;i++){
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    }
    int C[maxn];
    void solve(int x,int f){
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==f) continue;
            solve(v,x);
            C[x]+=C[v];
        }
    }
    int main(){
        scanf("%d",&n);mem(head,-1);
        rep(i,1,n) scanf("%d",&a[i]);
        rep(i,2,n){
            int p,w;scanf("%d%d",&p,&w);
            add(i,p,w);add(p,i,w);
        }    
        dfs(1,1);
        bz();
        for(int i=1;i<=n;i++){
            int now=i,dis=a[i];
            for(int j=19;j>=0;j--){
                if(d[now]-d[fa[now][j]]<=dis){
                    dis+=(d[fa[now][j]]-d[now]);
                    now=fa[now][j];
                }
            }
            C[fa[i][0]]++;C[fa[now][0]]--;
        }
        solve(1,0);
        rep(i,1,n){
            printf("%d ",C[i]);
        }
        puts("");
    }
    View Code
    Codeforces ID:Anonytt QQ: 847399102 可以添加&关注
  • 相关阅读:
    TS的一些小东西
    关于Vue懒加载问题
    react子传父
    MYSQL存储过程以及结果集
    MYSQL视图 事务 游标 索引及其使用
    MYSQL数据库的修复方法MAC
    MYSQL用户授权以及SQL语句
    MySQL数据库基础知识
    JavaScript对象
    JavaScript控制语句
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13585129.html
Copyright © 2011-2022 走看看