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

Posted cjlhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5390 tree 线段树套字典树 (看题解)相关的知识,希望对你有一定的参考价值。

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;


/*
*/

 

以上是关于HDU - 5390 tree 线段树套字典树 (看题解)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4819:Mosaic(线段树套线段树)

HDU 6096 树套树

bzoj3196 [TYVJ1730]二逼平衡树 树套树 线段树套ScapeGoat_Tree

#树套树,二维线段树#HDU 4819 Mosaic

HDU 4557 Tree(可持久化字典树 + LCA)

BZOJ 4605崂山白花蛇草水 替罪羊树套线段树