a 國共有 n 座城市,這些城市由 n-1 條道路相連,使得任意兩座城市可以互達,且路徑唯一。每座城市都有乙個幸運數字,以紀念碑的形式矗立在這座城市的正中心,作為城市的象徵。一些旅行者希望遊覽 a 國。旅行者計畫乘飛機降落在 x 號城市,沿著 x 號城市到 y 號城市之間那條唯一的路徑遊覽,最終從 y 城市起飛離開 a 國。在經過每一座城市時,遊覽者就會有機會與這座城市的幸運數字拍照,從而將這份幸運儲存到自己身上。然而,幸運是不能簡單疊加的,這一點遊覽者也十分清楚。他們迷信著幸運數字是以異或的方式保留在自己身上的。例如,遊覽者拍了 3 張**,幸運值分別是 5,7,11,那麼最終保留在自己身上的幸運值就是 9(5 xor 7 xor 11)。有些聰明的遊覽者發現,只要選擇性地進行拍照,便能獲得更大的幸運值。例如在上述三個幸運值中,只選擇 5 和 11 ,可以保留的幸運值為 14 。現在,一些遊覽者找到了聰明的你,希望你幫他們計算出在他們的行程安排中可以保留的最大幸運值是多少。
看到求異或最大值,是可以用線性基的,想到線性基是可以合併的,就可以用樹鏈剖分加線段樹維護。
#include
#include
#include
using
namespace
std;
const
int n = 20202;
typedef
long
long ll;
inline
char get(void)
return *s++;
}template
inline
void read(t &x)
struct lb
inline lb(void)
inline ll insert(ll x)
x ^= a[i];
}return x;
} inline ll &operator (int x)
inline ll max(void)
};struct edge
};edge g[n << 1];
int head[n];
ll val[n];
int fa[n], dep[n], size[n], top[n], pos[n], son[n];
int gcnt, pcnt, n, q, x, y, f1, f2;
lb t[n << 3];
lb ans;
inline
void addedge(int from, int to)
inline lb merge(lb &a, lb &b)
void dfs1(int u)
}void dfs2(int u, int t)
void insert(int o, int l, int r, int pos, ll v)
void query(int o, int l, int r, int l, int r)
int main(void)
dfs1(1); dfs2(1, 1);
for (int i = 1; i <= n; i++)
insert(1, 1, n, pos[i], val[i]);
while (q--)
query(1, 1, n, pos[f1], pos[x]);
x = fa[f1]; f1 = top[x];
}if (dep[x] > dep[y]) swap(x, y);
query(1, 1, n, pos[x], pos[y]);
printf("%lld\n", ans.max());
} return
0;}
學習線性基 bzoj 4568 幸運數字
好久沒寫部落格了,最近學習了一下新姿勢 線性基,這個就很厲害了。線性基其實很好理解。會線性基可以直接跳過下面的部分。我們先丟擲一道簡單的題 給你乙個長度為n的序列,在其中任選數字求可以得到的最大異或和。我們知道任意兩個,和連續一段的最大異或和,可以用trie加貪心水掉,但這道題怎麼做呢?線性基就可以...
bzoj4568 樹上倍增 線性基 幸運數字
description a 國共有 n 座城市,這些城市由 n 1 條道路相連,使得任意兩座城市可以互達,且路徑唯一。每座城市都有乙個 幸運數字,以紀念碑的形式矗立在這座城市的正中心,作為城市的象徵。一些旅行者希望遊覽 a 國。旅行者計畫 乘飛機降落在 x 號城市,沿著 x 號城市到 y 號城市之間...
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...