zoukankan      html  css  js  c++  java
  • 2015 Multi-University Training Contest 8 hdu 5390 tree

    tree

    Time Limit: 8000ms
    Memory Limit: 262144KB
    This problem will be judged on HDU. Original ID: 5390
    64-bit integer IO format: %I64d      Java class name: Main
     
    Given a rooted tree(node 1 is the root) with n nodes. The ithnode has a positive value vi at beginning.
    We define the universal set S includes all nodes.
    There are two types of Memphis's operation.
    First, Memphis may change the value of one node. It's the first type operation:
    0  u  v   (uS,0v109)

    What's more, Memphis wants to know what's the maxinum of vuvt(tpath(u,root),  means  xor) . It's the second type operation:
    1  u   (uS)
     
     

    Input

    This problem has multi test cases(no more than 3). 
    The first line contains a single integer T, which denotes the number of test cases.
    For each test case,the first line contains two non-negative integer n,m(1n,m100000) - the number of nodes and operations.
    The second line contains n1 non-negative integer f2fn(fi<i) - the father of ithnode.
    The third line contains n non-negative integer v1vn(0vi109) - the value of nodes at beginning.
    Follow m lines describe each operation.
     

    Output

    For each test cases,for each second operation print a non-negative integer.
     

    Sample Input

    1
    10 10
    1 1 2 2 3 1 2 3 5
    23512 460943 835901 491571 399045 97756 413210 800843 283274 106134
    0 7 369164
    0 7 296167
    0 6 488033
    0 7 187367
    0 9 734984
    1 6
    0 5 329287
    1 5
    0 7 798656
    1 10

    Sample Output

    766812
    351647
    431641

    Source

     
    解题:看到这位大神的代码后,看了一上午,终于看明白了,真的很神,离线做法,统一查询
     
    先说说为什么要用线段树,因为我们发现是树,树任意两点之间只有唯一的路径,dfs序列,然后更新以后,为什么没有放到叶子结点?因为这是父节点,其代表区间内的任意节点到根的路径,必须经过父节点
     
    所以当然是挂在区间上,而不是放到叶子,那么查询情况呢?我们是从根一直到叶子结点,一直路径上经过的结点,都把查询加入了,因为要查询的结点到根,也是必须经过这些结点的
     
    那么字典树所谓何用,字典树是用来快速求解异或最大值的,利用的是贪心的思想,优先让高位变成1
     
    好啦!代码已经灰常灰常灰常清晰了。。。。
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <vector>
      5 #pragma comment(linker, "/STACK:102400000,102400000")
      6 using namespace std;
      7 const int maxn = 100100;
      8 struct arc{
      9     int to,next;
     10     arc(int x = 0,int y = -1){
     11         to = x;
     12         next = y;
     13     }
     14 }e[maxn<<1];
     15 struct node{
     16     int val,foo,op;
     17     node(int x = 0,int y = 0,int z = 0){
     18         val = x;
     19         foo = y;
     20         op = z;
     21     }
     22 };
     23 struct trie{
     24     int tot,root,b[maxn*100][2],cnt[maxn*100];
     25     int newnode(){
     26         b[tot][0] = b[tot][1] = cnt[tot] = 0;
     27         return tot++;
     28     }
     29     void init(){
     30         tot = 0;
     31         root = newnode();
     32     }
     33     void insert(int val,int f,int root){
     34         for(int i = 30; i >= 0; --i){
     35             int bt = ((val>>i)&1);
     36             int &son = bt?b[root][1]:b[root][0];
     37             if(!son) son = newnode();
     38             root = son;
     39             cnt[root] += f;
     40         }
     41     }
     42     int query(int val,int root,int ret = 0){
     43         for(int i = 30; i >= 0; --i){
     44             int bt = ((val>>i)&1);
     45             int son[2] = {b[root][1],b[root][0]};
     46             if((!son[0] || !cnt[son[0]]) && (!son[1] || !cnt[son[1]])) return 0;
     47             if(son[bt] && cnt[son[bt]]){
     48                 ret |= (1<<i);
     49                 root = son[bt];
     50             }else root = son[bt^1];
     51         }
     52         return ret;
     53     }
     54 }T;
     55 int head[maxn],L[maxn],R[maxn],ans[maxn],tot,times;
     56 vector<node>g[maxn<<2];
     57 void add(int u,int v){
     58     e[tot] = arc(v,head[u]);
     59     head[u] = tot++;
     60 }
     61 void dfs(int u){
     62     L[u] = ++times;
     63     for(int i = head[u]; ~i; i = e[i].next) dfs(e[i].to);
     64     R[u] = times;
     65 }
     66 void build(int L,int R,int v){
     67     g[v].clear();
     68     if(L == R) return;
     69     int mid = (L + R)>>1;
     70     build(L,mid,v<<1);
     71     build(mid+1,R,v<<1|1);
     72 }
     73 void update(int L,int R,int lt,int rt,int val,int f,int v){
     74     if(lt <= L && rt >= R){
     75         g[v].push_back(node(val,f,0));
     76         return;
     77     }
     78     int mid = (L + R)>>1;
     79     if(lt <= mid) update(L,mid,lt,rt,val,f,v<<1);
     80     if(rt > mid) update(mid+1,R,lt,rt,val,f,v<<1|1);
     81 }
     82 void query(int L,int R,int p,int val,int id,int v){
     83     g[v].push_back(node(val,id,1));
     84     if(L == R) return;
     85     int mid = (L + R)>>1;
     86     if(p <= mid) query(L,mid,p,val,id,v<<1);
     87     else query(mid+1,R,p,val,id,v<<1|1);
     88 }
     89 int val[maxn];
     90 void query(int L,int R,int v){
     91     T.init();
     92     for(int i = 0,sz = g[v].size(); i < sz; ++i){
     93         if(g[v][i].op == 0) T.insert(g[v][i].val,g[v][i].foo,T.root);
     94         else ans[g[v][i].foo] = max(ans[g[v][i].foo],T.query(g[v][i].val,T.root));
     95     }
     96     if(L == R) return;
     97     int mid = (L + R)>>1;
     98     query(L,mid,v<<1);
     99     query(mid+1,R,v<<1|1);
    100 }
    101 int main(){
    102     int kase,n,m,fa,op,w;
    103     scanf("%d",&kase);
    104     while(kase--){
    105         scanf("%d%d",&n,&m);
    106         memset(head,-1,sizeof head);
    107         times = tot = 0;
    108         for(int i = 2; i <= n; ++i){
    109             scanf("%d",&fa);
    110             add(fa,i);
    111         }
    112         dfs(1);
    113         build(L[1],R[1],1);
    114         for(int i = 1; i <= n; ++i){
    115             scanf("%d",val+i);
    116             update(1,n,L[i],R[i],val[i],1,1);
    117         }
    118         for(int i = 1; i <= m; ans[i++] = -1){
    119             scanf("%d",&op);
    120             if(op){
    121                 scanf("%d",&fa);
    122                 query(1,n,L[fa],val[fa],i,1);
    123             }else{
    124                 scanf("%d%d",&fa,&op);
    125                 update(1,n,L[fa],R[fa],val[fa],-1,1);
    126                 val[fa] = op;
    127                 update(1,n,L[fa],R[fa],op,1,1);
    128             }
    129         }
    130         query(1,n,1);
    131         for(int i = 1; i <= m; ++i)
    132             if(ans[i] != -1) printf("%d
    ",ans[i]);
    133     }
    134     return 0;
    135 }
    View Code

     

  • 相关阅读:
    angular2+ 使用ant.design 的 select组件时(nz-select)下拉框没有脱离文档流,直接撑开页面展示的问题
    element 获取table组件的下标
    调幅调频调相位
    Mongoose基于MongoDB建模并设置关联
    Xavier上TensorRT和Pytorch运行时间对比
    理解vue实例的生命周期和钩子函数
    [Vue]组件——.sync 修饰符实现对prop 进行“双向绑定”(子组件向父组件传值)
    vm.$attrs 【Vue 2.4.0新增inheritAttrs,attrs详解】
    (转)vue v-on修饰符
    Vue中的computed属性
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4734047.html
Copyright © 2011-2022 走看看