• D.树上求和


    D.树上求和

    给你一棵根为1的有N个节点的树,以及Q次操作。
    每次操作诸如:
    1 x y:将节点x所在的子树的所有节点的权值加上y
    2 x:询问x所在子树的所有节点的权值的平方和,答案模23333后输出

    做法倒是好想(但是尽量用结构体数组,不然不好写,原本没有结构体找bug好久,然后又改写的),假设一个点原本是x , 然后加上y , 变大了y * y + 2 * x * y,将一个子树看成dfs序就是一段区间, 那么就是sum += y * y * len + 2 * res * x , len是区间长度,res 是区间和, sum是区间平方和

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <unordered_map>
    #include <vector>
    #include <map>
    #include <list>
    #include <queue>
    #include <cstring>
    #include <cstdlib>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <set>
    #pragma GCC optimize(3 , "Ofast" , "inline")
    using namespace std ;
    #define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
    #define x first
    #define y second
    #define ls rt << 1
    #define rs rt << 1 | 1
    typedef long long ll ;
    const double esp = 1e-6 , pi = acos(-1) ;
    typedef pair<int , int> PII ;
    const int N = 1e6 + 10 , INF = 0x3f3f3f3f , mod = 23333 ;
    ll in()
    {
      ll x = 0 , f = 1 ;
      char ch = getchar() ;
      while(!isdigit(ch)) {if(ch == '-') f = -1 ; ch = getchar() ;}
      while(isdigit(ch)) x = x * 10 + ch - 48 , ch = getchar() ;
      return x * f ;
    }
    int sum[N] , sum1[N] , lazy2[N] , lazy3[N] ,  cnt = 0 , lf[N] , rg[N] , d[N] , p[N] ;
    vector<int> v[N] ;
    void dfs(int u , int f){
      lf[u] = ++ cnt ;
      p[cnt] = d[u] ;
      for(auto x : v[u]) {
        if(x == f) continue ;
        dfs(x , u) ;
      }
      rg[u] = ++ cnt ;
      p[cnt] = d[u] ;
    }
    struct node {
      ll sum , sum1 , lazy , l , r ;
    }t[N * 4];
    void pushup(int rt){
        t[rt].sum = (t[ls].sum + t[rs].sum) % mod ;
        t[rt].sum1 = (t[ls].sum1 + t[rs].sum1) % mod ;
        return ;
    }
    void build(int rt , int l , int r){
      t[rt].l = l , t[rt].r = r ;
      if(l == r) {
        t[rt].sum = 1ll * p[l] * p[l] % mod ;
        t[rt].sum1 = p[l] % mod ;
        return ;
      }
      int mid = l + r >> 1 ;
      build(ls , l , mid) ;
      build(rs , mid + 1 , r) ;
      pushup(rt) ;
      return ;
    }
    void down(int rt){
       if(t[rt].lazy) {
         ll &v = t[rt].lazy ;
         (t[ls].lazy += v) %= mod ;
         (t[rs].lazy += v) %= mod ;
         ll ll = t[ls].r - t[ls].l + 1 , rr = t[rs].r - t[rs].l + 1 ;  ;
         t[ls].sum = (t[ls].sum + ll * v * v % mod + t[ls].sum1 * 2 * v % mod) % mod ;
         t[rs].sum = (t[rs].sum + rr * v * v% mod + t[rs].sum1 * 2 * v % mod) % mod ;
         t[ls].sum1 = (t[ls].sum1 + ll * v % mod ) % mod ;
         t[rs].sum1 = (t[rs].sum1 + rr * v % mod ) % mod ;
         v = 0 ;
       }
       return ;
    }
    void update(int rt , int l , int r , int k){
    
      if(l <= t[rt].l && t[rt].r <= r) {
        t[rt].sum = (t[rt].sum + 1ll * (t[rt].r - t[rt].l + 1) * k % mod * k % mod + t[rt].sum1 * 2 * k % mod) % mod ;
        t[rt].sum1 = (t[rt].sum1 + 1ll * (t[rt].r - t[rt].l + 1) * k) % mod ;
        t[rt].lazy += k , t[rt].lazy %= mod ;
        down(rt) ;
        return ;
      }
      down(rt) ;
      int mid = t[rt].l + t[rt].r >> 1;
      if(l <= mid) update(ls , l , r , k) ;
      if(r > mid) update(rs , l , r , k) ;
      pushup(rt) ;
      return ;
    }
    ll query(int rt , int l , int r){
      if(t[rt].l >= l && t[rt].r <= r) {
        return t[rt].sum ;
      }
      down(rt) ;
      ll mid = t[rt].l + t[rt].r >> 1 , res =  0 ;
      if(l <= mid) (res += query(ls , l , r)) %= mod ;
      if(r > mid) (res += query(rs , l , r)) %= mod ;
      pushup(rt) ;
      return res % mod ;
    }
    int ask(int rt , int l , int r){
      if(t[rt].l >= l && t[rt].r <= r) {
        return t[rt].sum1 % mod ;
      }
      down(rt) ;
      int mid = t[rt].l + t[rt].r >> 1 , res =  0 ;
      if(l <= mid) (res += ask(ls , l , r)) %= mod ;
      if(r > mid) (res += ask(rs , l , r)) %= mod ;
      pushup(rt) ;
      return res ;
    }
    ll qmi(ll a , ll b){
      ll res = 1 ;
      while(b)
      {
        if(b & 1) res = res * a % mod ;
        a = a * a % mod ;
        b >>= 1 ;
      }
      return res ;
    }
    int main()
    {
      int n = in() , m = in() ;
      for(int i = 1; i <= n ;i ++ ) d[i] = in() ;
      for(int i = 1; i < n ;i ++ )
       {
         int a= in() , b = in() ;
         v[a].push_back(b) , v[b].push_back(a) ;
       }
       dfs(1 , 0) ;
       build(1 , 1 , cnt) ;
       while(m --) {
         int op = in() , x = in() , y ;
         if(op == 2) cout << query(1 , lf[x] , rg[x]) * qmi(2 , mod - 2) % mod << endl  ;
         else if(op == 1) y = in() , update(1 , lf[x] , rg[x] , y) ;
         else cout << ask(1 , lf[x] , rg[x]) << " C " << endl ;
       }
      return 0 ;
    }
    /*
    6 10
    10000 10000 100000 10000 10000 100000
    1 2
    1 3
    2 5
    2 6
    5 4
    1 1 100000
    2 1
    1 5 12000
    2 1
    1 2 10
    2 1
    1 4 10300
    2 1
    2 3
    2 4
    
    */
    
    
  • 相关阅读:
    php中的md5()的安全问题
    爆破之中文转换成字母脚本
    MYSQL数据库封装类
    SQL执行结果操作
    原生和jquery 的 ajax
    Ajax实例OR技术原理 转自 (http://blog.csdn.net/evankaka )
    JQuery常用事件
    分页原理
    JQuery中$.ajax()方法参数
    session和cookie的作用和原理
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/13303100.html
Copyright © 2020-2023  润新知