题意:
给你一棵1e5的有根树,每个节点有点权,1e5个询问(u,x),问你子树u中与x异或最大的值是多少
思路:
自下而上启发式合并01字典树,注意合并时清空trie
线段树、字典树这种结构确定的数据结构,启发式合并的时候不需要考虑次序,复杂度都是nlogn
代码:
2200 / 10000ms , 60 / 128 M
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) #define LLONG_MAX 9223372036854775807 using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef long long LL; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 2e6+11; const int maxm = 1e5+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); int tot; int n, q; int a[maxm]; int root[maxm]; int trie[maxn][2]; vector<int>v[maxm]; queue<int>pool; int build(){ if(!pool.empty()){ int x = pool.front(); pool.pop(); return x; } ++tot; return tot; } void insert(int root, int t){ for(int i = 31; i >= 0; i--){ int x = (t>>i)&1; if(!trie[root][x])trie[root][x]=build(); root = trie[root][x]; } return; } int query(int root, int t){ int ans = 0; for(int i = 31; i >= 0; i--){ int x = (t>>i)&1; if(trie[root][x^1]){ ans|=(1<<i); root = trie[root][x^1]; } else root = trie[root][x]; } return ans; } vector<PI>ask[maxn]; void del(int x){ if(!x)return; pool.push(x); return; } int merge(int p, int q){ if(!p)return q; if(!q)return p; trie[p][0] = merge(trie[p][0], trie[q][0]); trie[p][1] = merge(trie[p][1], trie[q][1]); trie[q][0]=trie[q][1]=0; del(q); return p; } int ans[maxn]; void dfs(int x){ root[x] = build(); insert(root[x], a[x]); for(int i = 0; i < (int)v[x].size(); i++){ int y = v[x][i]; dfs(y); root[x] = merge(root[x],root[y]); } for(int i = 0; i < (int)ask[x].size(); i++){ ans[ask[x][i].fst] = query(root[x], ask[x][i].sc); } return; } int main(){ while(~scanf("%d %d", &n, &q)){ tot = 0; while(!pool.empty())pool.pop(); mem(trie,0); for(int i = 1; i <= n; i++){ v[i].clear(); ask[i].clear(); root[i]= 0; scanf("%d", &a[i]); } for(int i = 2; i <= n; i++){ int x; scanf("%d", &x); v[x].pb(i); } for(int i = 1; i <= q; i++){ int u, x; scanf("%d %d", &u, &x); ask[u].pb(make_pair(i,x)); } dfs(1); for(int i = 1; i <= q; i++){ printf("%d ",ans[i]); } del(root[1]); } return 0; } /* 2 2 1 2 1 1 3 2 1 3 2 1 2 3 1 1 3 4 1 3 11 4 1 2 3 4 5 6 7 8 9 10 11 1 1 1 2 2 3 4 4 4 5 2 5 3 6 1 2 8 7 100000 2 1 55 2 33 */