zoukankan      html  css  js  c++  java
  • Codeforces 396C

    题意略。

    思路:

    将树上的节点编好dfs序,然后就可以用树状数组区间修改点查询了。

    我们用 lft[v] 和 rht[v]来表示v的子树在dfs序中的左端和右端,这样才方便我们对树状数组的操作。

    其实这个题目的问题在于每个点在修改时,修改的值不是一定的,会发生变化。

    我是将加上的值和减去的值分开了。

    开两个树状数组,一个记录加:在我们进行加操作的时候,加上的值是x + deep[v] * k。

    一个记录减:在我们进行减操作的时候,减去的值就是k。

    最后在获取答案的时候,ans = sum(v,0) - deep[v] * sum(v,1)。

    详见代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 3e5 + 5;
    const LL mod = 1e9 + 7;
    
    int lft[maxn],rht[maxn],n,q,cnt;
    LL deep[maxn],BIT[2][maxn];
    vector<int> graph[maxn];
    
    void dfs(int cur,int d){
        lft[cur] = ++cnt;
        deep[cur] = d;
        for(int i = 0;i < graph[cur].size();++i){
            int v = graph[cur][i];
            dfs(v,d + 1);
        }
        rht[cur] = cnt;
    }
    int lowbit(int k){
        return (k & -k);
    }
    void add(int pos,LL val,int idx){
        while(pos <= n){
            BIT[idx][pos] += val;
            BIT[idx][pos] %= mod;
            pos += lowbit(pos);
        }
    }
    LL sum(int pos,int idx){
        LL ret = 0;
        while(pos > 0){
            ret += BIT[idx][pos];
            pos -= lowbit(pos);
            ret %= mod;
        }
        return ret;
    }
    
    int main(){
        scanf("%d",&n);
        int pi;
        for(int i = 2;i <= n;++i){
            scanf("%d",&pi);
            graph[pi].push_back(i);
        }
        dfs(1,1);
        scanf("%d",&q);
        for(int i = 0;i < q;++i){
            int type;
            scanf("%d",&type);
            if(type == 1){
                int v;
                LL x,k;
                scanf("%d%lld%lld",&v,&x,&k);
                LL val = (x + deep[v] * k) % mod;
                add(lft[v],val,0);
                add(rht[v] + 1,-val,0);
                add(lft[v],k,1);
                add(rht[v] + 1,-k,1);
            }
            else{
                int v;
                scanf("%d",&v);
                int pos = lft[v];
                LL part1 = sum(pos,0);
                LL part2 = sum(pos,1);
                part2 = part2 * deep[v] % mod;
                LL ans = ((part1 - part2) % mod + mod) % mod;
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    react的CSS中 :global的含义
    TypeScript中的问号 ? 与感叹号 ! 的含义
    移动端1px问题的解决方案
    原生js实现call,apply以及bind
    哪些场景不能使用箭头函数
    线性渐变、径向渐变以及圆锥渐变
    vue 开发中实现provide和inject实现依赖注入
    inline-block元素去除间隙
    clientWidth、offsetWidth、scrollWidth的区别
    session、token和cookie
  • 原文地址:https://www.cnblogs.com/tiberius/p/9409445.html
Copyright © 2011-2022 走看看