• 颓红警


    事实证明,小可爱是最可爱的嘤! ——佚名
    现在小可爱在颓游戏,但是他遇到了一个问题:
    小可爱率领的部队现在面对的是敌军在这一地区的驻军,敌国战争机器的运作很大程度上依赖指挥,所以敌军内部是严明分级的,就是说,全部敌军可以看作一棵树,每只敌军部队(树上每个节点)有其战斗力。你可以对任意敌军部队发动进攻,小可爱的部队有战斗力p,意味着他的每次进攻将使得被进攻的这支部队的战斗力减少p,对上级指挥系统的打击同时会影响其下级部队。具体来说,当他对点i发动进攻,部队i的战力减少p的同时,对于其子树内点j,部队j的战力减少Max(0,p−dis(i,j)2)(dis(i,j)表示点i,j间简单路径的长度)。如果某支部队战力小于0,那么这支部队就被消灭了,一支部队被消灭不会改变敌军编制(即这棵树的结构不会改变)。
    小可爱想知道,你的部队最少发动几次进攻,才能全歼敌军
    由于小可爱还要爆手速发展自己实力,所以把这个问题交给了你。
    小可爱因为太可爱了,所以受到了一些限制——只有在一个部队的祖先节点都被歼灭之后才能发动进攻去打它,否则它就会被这个部队的祖先节点攻击,这是他不愿意经历的。

    1. 树形结构 ‘
    2. 只能从上到下进行操作
    3. 每个节点值小于0的时候才不可以对其进行操作
    4. 1....i - 1中对i会产生影响的,只有令(p - dis[i , j]^2 > 0) , 也就是如果用深度表示dis , 那么就是(( dis[j] - dis[i] )^2 < p) , 就是(dis[j] - dis[i] <sqrt p), 也就是说对于i来说它的祖先节点只有距离它(sqrt p)以内的才会对i产生影响。
    5. 那么也就是说对于i来说,我们只关心距离当前点距离为(sqrt p)的点,大于这个的我们都不关心,这个可以用滑动窗口来维护
    6. 那么维护的内容是什么呢。$$p - dis[i , j] ^ 2 = p - (dis(j) - dis(i)) ^ 2 = p - dis(i) ^ 2 - dis(j) ^ 2+ 2 * dis(i)*dis(j)$$
    可以发现对于一个滑动窗口里面,(dis[j])是需要枚举的,(i)(j)的祖先节点,那么我们需要维护的也就是区间(dis[i] ^ 2 , dis[i]) , 还有(cnt * (p - dis[i] ^ 2)) ,这个(cnt)次数,dfs向下传的时候,就相当于区间加一,将当前点的贡献算一下, 同时需要将那一个上面不需要的一个祖先节点的贡献减掉

    在这里插入图片描述

    #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 = 1e9 + 7;
    int cinint(){  int t ; scanf("%d" , &t) ;  return t ;}
    int cinll(){ll t ;scanf("%lld" , &t) ;return t ;}
    ll a[N] , n , p ;
    vector<int> v[N] ;
    ll size[N] , size1[N] , size2[N] , len , cnt[N] , res[N] , ans = 0 ;
    void dfs(int u , int fa , ll d){
      if(d > len) {
        ll t = d - len ;
        size[u] -= cnt[t] ;
        size1[u] -= cnt[t] * t ;
        size2[u] -= cnt[t] * t * t ;
      }
      res[u] -= size[u] * (p - d * d) - size2[u] + 2 * size1[u] * d ;
      ll pos = 0 ;
      if(res[u] >= 0) pos = res[u] / p + 1 , ans += pos ;
      cnt[d] = pos ;
      for(auto x : v[u]) {
        if(x == fa) continue ;
        size[x] = size[u] + pos , size1[x] += size1[u] + pos * d , size2[x] += size2[u] + pos * d * d ;
        dfs(x , u , d + 1) ;
      }
    }
    int work()
    {
      n = cinint() , p = cinint() ;
      len = sqrt(p) + 1 ;
      for(int i = 1; i <= n ;i ++ ) res[i] = cinint() ;
      for(int i = 1; i < n ;i ++ ) {
        int a = cinint() , b = cinint() ;
        v[a].push_back(b) , v[b].push_back(a) ;
      }
      dfs(1 , 0 , 1) ;
      cout << ans << endl ;
      return 0 ;
    }
    int main()
    {
    
      work() ;
      return 0 ;
    }
    /*
    */
    
    
  • 相关阅读:
    《一个人的村庄》 ——刘亮程
    uva 11020
    Codeforces Round #190 (Div. 2) B. Ciel and Flowers
    hdu3308 线段树——区间合并
    线段树,区间更新
    vim 被墙
    ubuntu12.04 修复Grub2
    windows下mysql数据库忘记密码
    高性能的异步爬虫
    中间件
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/13362658.html
Copyright © 2020-2023  润新知