HDU - 5390 tree 线段树套字典树 (看题解)

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

HDU - 5390

看到的第一感觉就是树链剖分 + 线段树套字典树, 感觉复杂度不太对。

其实这种路径其实很特殊, 一个点改变只会影响它儿子到根的路径, 并且这种求最优值问题可以叠加。

所以我们修改的时候对对应dfs序打标记, 询问的时候在线段树上从上往下对每个对应区间求个最优值。

这样还会被卡MLE。。 需要分层优化一下。

#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 = 1e9 + 7; 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;}  //mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());  const int LOG = 30;  int n, m, v[N], tmp[N]; int qus[N][3]; int ans[N]; int Trietot; int ch[N * 40][2], sz[N * 40]; int mx = 0; int newNode() {     Trietot++;     assert(Trietot < N * 40);     chkmax(mx, Trietot);     ch[Trietot][0] = 0;     ch[Trietot][1] = 0;     sz[Trietot] = 0;     return Trietot; }  struct Trie {     int Rt;     void init() {         Rt = newNode();     }     void ins(int x) {         int u = Rt;         for(int i = LOG - 1; i >= 0; i--) {             sz[u]++;             if(!ch[u][x >> i & 1]) {                 ch[u][x >> i & 1] = newNode();             }             u = ch[u][x >> i & 1];         }         sz[u]++;     }     void del(int x) {         int u = Rt;         for(int i = LOG - 1; i >= 0; i--) {             sz[u]--;             u = ch[u][x >> i & 1];         }         sz[u]--;     }     int query(int x) {         int u = Rt, ret = 0;         if(!sz[u]) return 0;         for(int i = LOG - 1; i >= 0; i--) {             if(sz[ch[u][(x >> i & 1) ^ 1]]) {                 ret += 1 << i;                 u = ch[u][(x >> i & 1) ^ 1];             }             else {                 u = ch[u][x >> i & 1];             }         }         return ret;     } } T[N << 2];   #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 void build(int tar, int cur, int l, int r, int rt) {     if(cur == tar) {         T[rt].init();         return;     }     if(l == r) return;     int mid = l + r >> 1;     build(tar, cur + 1, lson);     build(tar, cur + 1, rson); } void update(int tar, int cur, int L, int R, int val, int l, int r, int rt) {     if(L > R) return;     if(L <= l && r <= R) {         if(cur == tar) {             if(val > 0) T[rt].ins(val);             else T[rt].del(-val);         }         return;     }     if(l == r) return;     int mid = l + r >> 1;     if(L <= mid) update(tar, cur + 1, L, R, val, lson);     if(R > mid) update(tar, cur + 1, L, R, val, rson); }  int query(int tar, int cur, int p, int val, int l, int r, int rt) {     if(cur == tar) {         return T[rt].query(val);     }     if(l == r) return 0;     int mid = l + r >> 1;     if(p <= mid) return query(tar, cur + 1, p, val, lson);     else return query(tar, cur + 1, p, val, rson); }  void initTrie(int depth) {     Trietot = 0;     build(depth, 0, 1, n, 1); }  vector<int> G[N]; int in[N], ot[N], idx;  void dfs(int u) {     in[u] = ++idx;     for(auto &v : G[u]) {         dfs(v);     }     ot[u] = idx; }  void init() {     idx = 0;     for(int i = 1; i <= n; i++) {         G[i].clear();     } }  int main() {     int T; scanf("%d", &T);     while(T--) {         scanf("%d%d", &n, &m);         init();         for(int i = 2; i <= n; i++) {             int par; scanf("%d", &par);             G[par].push_back(i);         }         for(int i = 1; i <= n; i++) {             scanf("%d", &v[i]);             tmp[i] = v[i];         }         for(int i = 1; i <= m; i++) {             scanf("%d%d", &qus[i][0], &qus[i][1]);             if(qus[i][0] == 0) scanf("%d", &qus[i][2]);             ans[i] = 0;         }         dfs(1);         for(int depth = 0; depth <= 17; depth++) {             initTrie(depth);              for(int i = 1; i <= n; i++) {                 v[i] = tmp[i];                 update(depth, 0, in[i], ot[i], v[i], 1, n, 1);             }             for(int i = 1; i <= m; i++) {                 if(!qus[i][0]) {                     update(depth, 0, in[qus[i][1]], ot[qus[i][1]], -v[qus[i][1]], 1, n, 1);                     v[qus[i][1]] = qus[i][2];                     update(depth, 0, in[qus[i][1]], ot[qus[i][1]], v[qus[i][1]], 1, n, 1);                 }                 else {                     chkmax(ans[i], query(depth, 0, in[qus[i][1]], v[qus[i][1]], 1, n, 1));                 }             }         }          for(int i = 1; i <= m; i++) {             if(qus[i][0]) {                 printf("%d\n", ans[i]);             }         }     }     return 0; }  /* */

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