【线性基合并 树链剖分】bzoj4568: [Scoi2016]幸运数字

板子题

Description

A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 
和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
可以保留的最大幸运值是多少。
 

Input

第一行包含 2 个正整数 n ,q,分别表示城市的数量和旅行者数量。第二行包含 n 个非负整数,其中第 i 个整
数 Gi 表示 i 号城市的幸运值。随后 n-1 行,每行包含两个正整数 x ,y,表示 x 号城市和 y 号城市之间有一
条道路相连。随后 q 行,每行包含两个正整数 x ,y,表示这名旅行者的旅行计划是从 x 号城市到 y 号城市。N
<=20000,Q<=200000,Gi<=2^60
 

Output

 输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。


 

题目分析

树剖/倍增的板子题

想用树剖来做一做,然而TLE了好几发。

发现自己常数意识太差,每次query时候都开一个线性基,活生生浪费10s+

  1 #include<bits/stdc++.h>
  2 #define ENS //__attribute__((optimize("-O2")))
  3 #define NES //__attribute__((optimize("-O2"))) //__inline__ __attribute__((always_inline))
  4 typedef long long ll;
  5 const int maxn = 20035;
  6 const int maxm = 40035;
  7 const int maxq = 200035;
  8 
  9 struct Linear
 10 {
 11     ll p[103];
 12     Linear(){memset(p, 0, sizeof p);}
 13     NES void insert(ll c)
 14     {
 15         for (int i=60, chk=0; i>=0&&!chk; i--)
 16             if (c>>i){
 17                 if (p[i]) c ^= p[i];
 18                 else p[i] = c, chk = 1;
 19             }
 20     }
 21     NES void merge(Linear b)
 22     {
 23         for (int i=60; i>=0; i--)
 24             if (b.p[i]) insert(b.p[i]);
 25     }
 26     NES ll max()
 27     {
 28         ll ret = 0;
 29         for (int i=60; i>=0; i--)
 30             if ((ret^p[i]) > ret) ret ^= p[i];
 31         return ret;
 32     }
 33 }f[maxn<<2];
 34 struct node
 35 {
 36     int fa,son,top,tot;
 37 }a[maxn];
 38 int n,q,chain[maxn],chTot,dep[maxn];
 39 int edgeTot,head[maxn],nxt[maxm],edges[maxm];
 40 ll g[maxn],cnVal[maxn];
 41 
 42 template <typename T> NES void read(T&x)
 43 {
 44     char cu=getchar();x=0;bool fla=0;
 45     while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}
 46     while(isdigit(cu))x=x*10+cu-'0',cu=getchar();
 47     if(fla)x=-x; 
 48 }
 49 void write(ll x){if (x/10) write(x/10);putchar('0'+x%10);}
 50 void writeln(ll x){write(x), putchar('\n');}
 51 NES void addedge()
 52 {
 53     int u,v;
 54     read(u), read(v);
 55     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
 56     edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
 57 }
 58 void dfs1(int x, int fa)
 59 {
 60     a[x].son = a[x].top = -1, a[x].fa = fa; 
 61     a[x].tot = 1, dep[x] = dep[fa]+1;
 62     for (int i=head[x]; i!=-1; i=nxt[i])
 63     {
 64         int v = edges[i];
 65         if (v!=fa){
 66             dfs1(v, x), a[x].tot += a[v].tot;
 67             if (a[x].son==-1||a[a[x].son].tot < a[v].tot) a[x].son = v;
 68         }
 69     }
 70 }
 71 void dfs2(int x, int top)
 72 {
 73     a[x].top = top, chain[x] = ++chTot, cnVal[chTot] = g[x];
 74     if (a[x].son==-1) return;
 75     dfs2(a[x].son, top);
 76     for (int i=head[x]; i!=-1; i=nxt[i])
 77     {
 78         int v = edges[i];
 79         if (v!=a[x].son&&v!=a[x].fa) dfs2(v, v);
 80     }
 81 }
 82 void build(int rt, int l, int r)
 83 {
 84     if (l==r){
 85         f[rt].insert(cnVal[l]);
 86         return;
 87     }
 88     int mid = (l+r)>>1;
 89     build(rt<<1, l, mid);
 90     build(rt<<1|1, mid+1, r);
 91     f[rt] = f[rt<<1], f[rt].merge(f[rt<<1|1]);
 92 }
 93 Linear query(int rt, int l, int r, int L, int R)
 94 {
 95     if (L <= l&&r <= R) return f[rt];
 96     int mid = (l+r)>>1;
 97     if (L <= mid&&R > mid){
 98         
 99         Linear tmp = query(rt<<1, l, mid, L, R);
100         tmp.merge(query(rt<<1|1, mid+1, r, L, R));
101         return tmp;
102     }else if (L <= mid) return query(rt<<1, l, mid, L, R);
103     else if (R > mid) return query(rt<<1|1, mid+1, r, L, R);
104 }
105 NES void queryChain()
106 {
107     Linear ret;
108     int x,y;
109     read(x), read(y);
110     while (a[x].top!=a[y].top)
111     {
112         if (dep[a[x].top] > dep[a[y].top]) std::swap(x, y);
113         ret.merge(query(1, 1, n, chain[a[y].top], chain[y]));
114         y = a[a[y].top].fa;
115     }
116     if (dep[x] > dep[y]) std::swap(x, y);
117     ret.merge(query(1, 1, n, chain[x], chain[y]));
118     writeln(ret.max());
119 }
120 ENS int main()
121 {
122     memset(head, -1, sizeof head);
123     read(n), read(q);
124     for (int i=1; i<=n; i++) read(g[i]);
125     for (int i=1; i<n; i++) addedge();
126     dfs1(1, 0), dfs2(1, 1);
127     build(1, 1, n);
128     while (q--) queryChain();
129     return 0;
130 }

 

 

END

posted @ 2018-12-29 13:15  AntiQuality  阅读(151)  评论(0编辑  收藏  举报