zoukankan      html  css  js  c++  java
  • 1076E

    题意:给出一棵根节点为1的树,执行m次修改操作,每次修改为a,b,c,表示a节点的子树中,距离a小于等于b的子节点的权值加上c,求m次操作后每个节点的权值

    分析:用线段树维护每层节点的权值,然后dfs遍历这颗树,当前节点有操作时,把当前节点的深度到被修改的最大深度都加上c(实际上只有当前节点的子节点才加c),而回朔的时候再将这个区间减c,这样就避免了对非子节点的影响

    AC代码(线段树的区间更新):

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=3e5+10;
    ll f[maxn],nex[maxn*2],to[maxn*2],cnt,level[maxn],n,m;
    ll ans[maxn],num[maxn*4],lazy[maxn*4];
    vector<pair<ll,ll>>ve[maxn];
    void add(int a,int b)
    {
        cnt++;
        to[cnt]=b;
        nex[cnt]=f[a];
        f[a]=cnt;
    }
    void updata(int st,int en,int l,int r,int rt,ll x)
    {
        //cout<<l<<" "<<r<<endl;
        if(st<=l&&en>=r)
        {
            num[rt]+=x*(r-l+1);
            lazy[rt]+=x;
            return ;
        }
        int mid=(l+r)/2;
        if(lazy[rt])
        {
            lazy[rt*2]+=lazy[rt];
            lazy[rt*2+1]+=lazy[rt];
            num[rt*2]+=lazy[rt]*(mid-l+1);
            num[rt*2+1]+=lazy[rt]*(r-mid);
            lazy[rt]=0;
        }
        if(st<=mid)updata(st,en,l,mid,rt*2,x);
        if(en>=mid+1)updata(st,en,mid+1,r,rt*2+1,x);
        num[rt]=num[rt*2]+num[rt*2+1];
    }
    ll quer(int x,int l,int r,int rt)
    {
        int mid=(l+r)/2;
        if(l==r)return num[rt];
        if(lazy[rt])
        {
            lazy[rt*2]+=lazy[rt];
            lazy[rt*2+1]+=lazy[rt];
            num[rt*2]+=lazy[rt]*(mid-l+1);
            num[rt*2+1]+=lazy[rt]*(r-mid);
            lazy[rt]=0;
        }
        if(x<=(l+r)/2)return quer(x,l,(l+r)/2,rt*2);
        else return quer(x,(l+r)/2+1,r,rt*2+1);
        num[rt]=num[rt*2]+num[rt*2+1];
    }
    void getlevel(int x,int l)
    {
        level[x]=l;
        for(int i=f[x]; i; i=nex[i])
        {
            int v=to[i];
            if(!level[v])getlevel(v,l+1);
        }
    }
    void dfs(int x,int pre)
    {
        for(int i=0; i<ve[x].size(); i++)
        {
            updata(level[x],level[x]+ve[x][i].first,1,n,1,ve[x][i].second);
        }
        ans[x]=quer(level[x],1,n,1);
        for(int i=f[x]; i; i=nex[i])
        {
            int v=to[i];
            if(v!=pre)
                dfs(v,x);
        }
        for(int i=0; i<ve[x].size(); i++)
        {
            updata(level[x],level[x]+ve[x][i].first,1,n,1,-ve[x][i].second);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=1; i<=n-1; i++)
        {
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        getlevel(1,1);
        cin>>m;
        for(int i=1; i<=m; i++)
        {
            ll a,b,c;
            cin>>a>>b>>c;
            ve[a].push_back(make_pair(b,c));
        }
    
        dfs(1,-1);
        for(int i=1; i<=n; i++)
            cout<<ans[i]<<" ";
        cout<<endl;
        return 0;
    }
    

      

    AC代码(树状数组的区间更新):

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=3e5+10;
    ll f[maxn],nex[maxn*2],to[maxn*2],cnt,n,m;
    ll ans[maxn],c1[maxn],c2[maxn];
    vector<pair<int,ll>>ve[maxn];
    void add1(int a,int b)
    {
        cnt++;
        to[cnt]=b;
        nex[cnt]=f[a];
        f[a]=cnt;
    }
    void add(int x,ll y)
    {
        for(int i=x; i<=n; i+=(i&-i))c1[i]+=y,c2[i]+=y*x;
    }
    ll quer(int x)
    {
        ll res=0;
        for(int i=x; i>0; i-=(i&-i))res+=((x+1)*c1[i]-c2[i]);
        return res;
    }
    void in_add(int l,int r,ll x)
    {
        add(l,x);
        add(r+1,-x);
    }
    void dfs(int x,int pre,int l)
    {
        for(int i=0; i<ve[x].size(); i++)
            in_add(l,l+ve[x][i].first,ve[x][i].second);
        ans[x]=quer(l)-quer(l-1);
        for(int i=f[x]; i; i=nex[i])
        {
            int v=to[i];
            if(v!=pre)
                dfs(v,x,l+1);
        }
        for(int i=0; i<ve[x].size(); i++)
            in_add(l,l+ve[x][i].first,-ve[x][i].second);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1; i<=n-1; i++)
        {
            int a,b;
            cin>>a>>b;
            add1(a,b);
            add1(b,a);
        }
        cin>>m;
        for(int i=1; i<=m; i++)
        {
            ll a,b,c;
            cin>>a>>b>>c;
            ve[a].push_back(make_pair(b,c));
        }
        dfs(1,-1,1);
        for(int i=1; i<=n; i++)
            cout<<ans[i]<<" ";
        cout<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    [转]在efcore 中创建类 通过实现IEntityTypeConfiguration<T>接口 实现实体类的伙伴类 实现FluentApi
    jboss反序列化漏洞(CVE-2017-12149)
    第一阶段 3、javascript
    vue创建新项目
    vue引入git项目运行测试相关
    javascript基础知识梳理
    关于模式识别作业——利用分类器实现手写数字识别
    Guava 学习
    读书清单
    @JsonInclude(Include.NON_NULL)全局配置
  • 原文地址:https://www.cnblogs.com/carcar/p/9957533.html
Copyright © 2011-2022 走看看