zoukankan      html  css  js  c++  java
  • LCP 5. 发 LeetCoin

    link

     解法:

    先DFS给每个节点一个id,然后可以获得每个节点这颗子树的区间(一定是连续的),这样就可以进行线段树的操作(单点修改,区间修改,和区间查询),

    #define LL long long
    const int maxn=50005;
    const int mod=1000000007;
    
    class Solution {
    public:
        int cnt;
        int N;
        LL sum[maxn<<2], lazy[maxn<<2];
        int in[maxn],out[maxn];
        vector<int> adj[maxn];
    
        void update_range(int tleft, int tright, int left, int right, int idx, int val){
            if(tleft>right || tright<left) return;
            if(tleft<=left && tright>=right){
                sum[idx]=(sum[idx]+val*(right-left+1)%mod)%mod;
                lazy[idx]=(lazy[idx]+val)%mod;
                return;
            }
            push_down(idx,left,right);
            int mid=(left+right)>>1;
            update_range(tleft,tright,left,mid,idx*2,val);
            update_range(tleft,tright,mid+1,right,idx*2+1,val);
            sum[idx]=(sum[idx*2]+sum[idx*2+1])%mod;
        }
    
        void update_single(int targetidx, int left, int right, int idx, int val){
            if(left>targetidx || right<targetidx) return;
            if(left==right) {
                sum[idx]+=val;
                sum[idx]%=mod;
                return;
            }
            push_down(idx,left,right);
            int mid=(left+right)/2;
            update_single(targetidx,left,mid,idx*2,val);
            update_single(targetidx,mid+1,right,idx*2+1,val);
            sum[idx]=(sum[idx*2]+sum[idx*2+1])%mod;
        }
    
        void push_down(int idx, int left, int right){
            int mid=(left+right)/2;
            sum[idx*2]=(sum[idx*2]+lazy[idx]*(mid-left+1)%mod)%mod;
            sum[idx*2+1]=(sum[idx*2+1]+lazy[idx]*(right-(mid+1)+1)%mod)%mod;
            lazy[idx*2]=(lazy[idx*2]+lazy[idx])%mod;
            lazy[idx*2+1]=(lazy[idx*2+1]+lazy[idx])%mod;
            lazy[idx]=0;
        }
    
        LL query(int qleft, int qright, int left, int right, int idx){
            if(qleft>right || qright<left) return 0;
            if(qleft<=left && qright>=right){
                return sum[idx];
            }
            push_down(idx,left,right);
            LL res=0;
            int mid=(left+right)>>1;
            LL l=query(qleft,qright,left,mid,idx*2);
            LL r=query(qleft,qright,mid+1,right,idx*2+1);
            res=(l+r)%mod;
            return res;
        }
    
        vector<int> bonus(int n, vector<vector<int>>& leadership, vector<vector<int>>& operations) {
            N=n;
            cnt=0;
            for(auto l:leadership){
                adj[l[0]].push_back(l[1]);
            }
            dfs(1);
            vector<int> res;
            for(auto ope:operations){
                if(ope[0]==1){
                    update_single(in[ope[1]],1,cnt,1,ope[2]);
                }else if(ope[0]==2){
                    update_range(in[ope[1]],out[ope[1]],1,cnt,1,ope[2]);
                }else {
                    LL ret=query(in[ope[1]],out[ope[1]],1,cnt,1);
                    ret%=mod;
                    res.push_back(ret);
                }
            }
            return res;
        }
    
        void dfs(int u){
            in[u]=++cnt;
            for(int c:adj[u]){
                dfs(c);
            }
            out[u]=cnt;
        }
    };
  • 相关阅读:
    10年学到的编程经验总结
    高效阅读源代码指南
    一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10
    如何用git将项目代码上传到github
    关于[].slice.call(arguments, 1) 的思考
    前端笔试题(一)
    2017年第一波JavaScript前端面试题
    2017前端面试题之综合篇(1)
    2017前端面试题之Js篇(1)
    前后端分离后各自职责
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12690135.html
Copyright © 2011-2022 走看看