HDU - 5788 Level Up 主席树 + 树状数组

匿名 (未验证) 提交于 2019-12-02 23:59:01

HDU - 5788

我们考虑把每个点遍历一遍, 把枚举的当前的这个点改成100000对答案的影响。

如果我们把 u 变成 100000, 受到影响的是 u 以及它的祖先,

我们记midu为子树u的中位数, nexmidu为子树u中位数的下一个数。

只有 a[ u ]的值小于等于祖先的mid, 才会改变祖先的薪水, 变成nexmidu。

所以我们用主席树求出每个子树的mid 和 nexmid。 然后dfs一遍整棵树, 用树状数组去更新答案。

#pragma GCC optimize(2) #pragma GCC optimize(3) #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0);  using namespace std;  const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1);  template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}  int n, a[N]; int needVal[N]; int addVal[N];  vector<int> G[N]; int in[N], ot[N], sz[N], idx;  LL ans, allVal;  struct ChairManTree {     int Rt[N], treecnt;     void init() {         treecnt = 0;     }     struct Node {         int sum, ls, rs;     } a[N * 20];     void update(int p, int val, int l, int r, int &x, int y) {         x = ++treecnt;         a[x] = a[y];         a[x].sum += val;         if(l == r) return;         int mid = l + r >> 1;         if(p <= mid) update(p, val, l, mid, a[x].ls, a[y].ls);         else update(p, val, mid + 1, r, a[x].rs, a[y].rs);     }     int query(int k, int l, int r, int x, int y) {         if(l == r) return l;         int mid = l + r >> 1;         if(a[a[x].ls].sum - a[a[y].ls].sum >= k) return query(k, l, mid, a[x].ls, a[y].ls);         else return query(k - a[a[x].ls].sum + a[a[y].ls].sum, mid + 1, r, a[x].rs, a[y].rs);     } } C;  struct Bit {     LL a[N];     void init() {         for(int i = 1; i < N; i++) {             a[i] = 0;         }     }     inline void update(int x, int v) {         for(int i = x; i < N; i += i & -i) {             a[i] += v;         }     }     inline LL sum(int x) {         LL ans = 0;         for(int i = x; i; i -= i & -i) {             ans += a[i];         }         return ans;     } } Tree;  int dfs(int u) {     in[u] = ++idx;     C.update(a[u], 1, 1, 100000, C.Rt[idx], C.Rt[idx - 1]);     sz[u] = 1;     for(auto &v : G[u]) {         dfs(v);         sz[u] += sz[v];     }     ot[u] = idx; }  void solve(int u) {     Tree.update(100001 - needVal[u], addVal[u]);     chkmax(ans, Tree.sum(100000 - a[u] + 1));     for(auto &v : G[u]) {         solve(v);     }     Tree.update(100001 - needVal[u], -addVal[u]); }  void init() {     ans = allVal = idx = 0;     C.init(); Tree.init();     for(int i = 1; i <= n; i++) {         G[i].clear();     } } int main() {     while(scanf("%d", &n) != EOF) {         init();         for(int i = 1; i <= n; i++) {             scanf("%d", &a[i]);         }         for(int i = 2; i <= n; i++) {             int p; scanf("%d", &p);             G[p].push_back(i);         }         dfs(1);         for(int i = 1; i <= n; i++) {             if(sz[i] == 1) {                 needVal[i] = a[i];                 addVal[i] = 100000 - a[i];                 allVal += a[i];             }             else {                 int mid = sz[i] + 1 >> 1;                 needVal[i] = C.query(mid, 1, 100000, C.Rt[ot[i]], C.Rt[in[i] - 1]);                 addVal[i] = C.query(mid + 1, 1, 100000, C.Rt[ot[i]], C.Rt[in[i] - 1]) - needVal[i];                 allVal += needVal[i];             }         }         solve(1);         printf("%lld\n", ans + allVal);     }     return 0; }  /* */

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!