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

 

原文地址:https://www.cnblogs.com/crackpotisback/p/4734047.html