日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

zzuli 2520: 大小接近的点对

發布時間:2024/4/18 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zzuli 2520: 大小接近的点对 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題意

給你一棵樹,每個節點有一個權值。詢問每個節點有多少個點對,滿足以該節點為根節點uuu與它的所有子節點vvv,并且∣val[u]?val[v]∣≤K\left|val[u] - val[v] \right|\leq Kval[u]?val[v]K

思路

  • 比賽的時候想到一個思路:就是每次從葉子節點向根節點返回,每次把經過的點加入集合,并滿足根節點的數量。沒時間寫了,回來實現一下發現超時,就可能樹上有一個長鏈,在底層有很多葉子節點,這樣每次相當于便利了一棵樹N2N^2N2的復雜度。
  • 再次向學長請教(學長好厲害啊^ _ ^)。
  • 按照dfsdfsdfs順序維護一個樹狀數組,在剛進入節點的時候先計算滿足根節點的個數tmptmptmp,然后對子節點進行dfsdfsdfs,在回溯的時候插入當前點再次統計滿足根節點的情況sumsumsum,那么sum?tmpsum - tmpsum?tmp就是當前根節點能與子節點形成的點對,同時加上所有子樹的和就是當前根節點的答案。
  • 為什么在第一次進入節點的時候統計答案呢?
    剛進入節點的時候,樹狀數組已經插入了一些節點的值,而這些值并不是當前節點的子節點,所以它不會對節點有貢獻。
  • 權值很大需要離散。
#include <bits/stdc++.h> #define LL long long #define P pair<int, int> #define lowbit(x) (x & -x) #define mem(a, b) memset(a, b, sizeof(a)) #define mid ((l + r) >> 1) #define lc rt<<1 #define rc rt<<1|1 using namespace std; const int maxn = 1e5 + 7; int tot; vector<int> g[maxn]; LL a[maxn], b[maxn], c[maxn], ans[maxn], n, k; void Add(int x) {x++;while (x <= n) {c[x]++;x += lowbit(x);} } LL Sum(int x) {x++;LL ans = 0;while (x) {ans += c[x];x -= lowbit(x);}return ans; } void dfs(int x) {int l, r;l = lower_bound(b, b + tot, a[x-1]-k) - b - 1;r = upper_bound(b, b + tot, a[x-1]+k) - b - 1;ans[x] -= Sum(r) - Sum(l);LL sum = 0;for (int it : g[x]) {dfs(it);sum += ans[it];}int pos = lower_bound(b, b + tot, a[x-1]) - b;Add(pos);l = lower_bound(b, b + tot, a[x-1]-k) - b - 1;r = upper_bound(b, b + tot, a[x-1]+k) - b - 1;ans[x] += Sum(r) - Sum(l) + sum;return; } int main () {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);scanf("%lld %lld", &n, &k);for (int i = 0; i < n; ++i) {scanf("%lld", &a[i]);b[i] = a[i];}sort(b, b + n);tot = unique(b, b + n) - b;for (int i = 2, x; i <= n; ++i) {scanf("%d", &x);g[x].push_back(i);}dfs(1);for (int i = 1; i <= n; ++i) {printf("%lld\n", ans[i]);}return 0; }

總結

以上是生活随笔為你收集整理的zzuli 2520: 大小接近的点对的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。