• P4592 [TJOI2018]异或


    Problem

    • 1 (x,y):查询节点(x)的子树中与(y)异或结果的最大值
    • 2 (x,y,z):查询路径(x)(y)上点与(z)异或结果最大值

    看到区间异或的最大值 不难想到 可持久化trie

    用树剖把这些剖成链 每次就是链的查询。。这样就可以了。

    
    #include<bits/stdc++.h>
    using namespace std ;
    int n , q ;
    const int N = 1e5 + 10 ;
    struct node { int v , nxt ; } e[N << 1] ;
    int val[N] ;
    int head[N] , cnt = 0 ;
    inline void add(int u , int v) { e[++ cnt] = { v , head[u] } ; head[u] = cnt ; }
    int size[N] , son[N] , fa[N] , d[N] ;
    inline void dfs1(int u) { size[u] = 1 ;
      for(int i = head[u] ; i ; i = e[i].nxt) {
        int v = e[i].v;
        if(v == fa[u]) continue ;
        fa[v] = u ; d[v] = d[u] + 1 ;
        dfs1(v) ;
        size[u] += size[v] ;
        if(size[v] > size[son[u]]) son[u] = v ;
      }
    }
    int top[N] , id[N] , idx = 0 , a[N] ;
    inline void dfs2(int u , int t) {
      top[u] = t ; id[u] = ++ idx ; a[idx] = val[u] ;
      if(! son[u]) return ; dfs2(son[u] , t) ;
      for(int i = head[u] ; i ; i = e[i].nxt) {
        int v = e[i].v ;
        if(v == fa[u]) continue ;
        if(v == son[u]) continue ;
        dfs2(v , v) ;
      }
    }
    int tot = 0 ;
    int t[N] ; int ch[N << 5][2] ;
    int sz[N << 5] ;
    inline void upd(int x , int p , int q) {
    	ch[p][0] = ch[q][0] ; ch[p][1] = ch[q][1] ; sz[p] = sz[q] + 1 ;
    	for(register int i = 29 ; ~ i ; i --) {
    		int c = (x >> i) & 1 ;
    		ch[p][c] = ++ tot ;
    		p = ch[p][c] ;
    		q = ch[q][c] ;
    		ch[p][0] = ch[q][0] ;
    		ch[p][1] = ch[q][1] ;
    		sz[p] = sz[q] + 1 ;
    	}
    }
    inline int query(int x , int p , int q) {
      int res = 0 ;
    	for(register int i = 29 ; ~ i ; i --) {
    		int c = (x >> i) & 1 ;
    		if(sz[ch[q][c ^ 1]] - sz[ch[p][c ^ 1]]) res |= 1 << i , p = ch[p][c ^ 1] , q = ch[q][c ^ 1] ;
    		else p = ch[p][c] , q = ch[q][c] ;
    	} return res ;
    }
    inline int query_range(int x , int y , int val) {
      int fx = top[x] , fy = top[y] ; int res = 0 ;
      while(fx ^ fy) {
        if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
        res = max(res , query(val , t[id[fx] - 1] , t[id[x]])) ;
        x = fa[fx] , fx = top[x] ;
      }
      if(d[x] > d[y]) swap(x , y) ;
      res = max(res , query(val , t[id[x] - 1] , t[id[y]])) ;
      return res ;
    }
    signed main() {
      ios :: sync_with_stdio(false) ;
      cin.tie(nullptr) ;
      cout.tie(nullptr) ;
      cin >> n >> q ;
      for(register int i = 1 ; i <= n ; i ++) cin >> val[i] ;
      for(register int i = 1 ; i <= n - 1 ; i ++) {
        int u , v ; cin >> u >> v ;
        add(u , v) ; add(v , u) ;
      } dfs1(1) ; dfs2(1 , 1) ;
      for(register int i = 1 ; i <= n ; i ++) t[i] = ++ tot , upd(a[i] , t[i] , t[i - 1]) ;
      for(register int i = 1 ; i <= q ; i ++) {
        int opt ; cin >> opt ;
        if(opt == 1) {
          int x , y ;
          cin >> x >> y ;
          cout << query(y , t[id[x] - 1] , t[id[x] + size[x] - 1]) << '
    ' ;
        }
        else {
          int x , y , z ;
          cin >> x >> y >> z ;
          cout << query_range(x , y , z) << '
    ' ;
        }
      }
      return 0 ;
    }
    
  • 相关阅读:
    数据结构学习之前言,为年后换新工作做准备
    马云不想成为“马云”
    2014找工作总结-机会往往留给有准备的人
    数据分析≠Hadoop+NoSQL,不妨先看完善现有技术的10条捷径
    做个犀利的码农:如何持续培养/更新自己的开发技能
    Google七夕情人节Doodle背后技术揭秘
    把帖子用循环显示出来
    php验证登录
    用户注册
    form 表单用php来跳转页面
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11771880.html
Copyright © 2020-2023  润新知