• 洛谷 P4592: bzoj 5338: [TJOI2018]异或


    题目传送门:洛谷P4592

    题意简述:

    题面说的很清楚了。

    题解:

    发现没有修改很快乐。再看异或最大值操作,很容易想到可持久化 01trie。

    这里要把 01trie 搬到树上,有点难受。

    树剖太捞了,考虑 DFS 序。

    子树查询转成 DFS 序上一段区间,而链上查询转成两条链。

    所以维护两(个?)种可持久化 01trie,一个按照 DFS 序,另一个按照从根到结点的路径。

    还要求 LCA,这里我写了个倍增。

    #include <cstdio>
    
    inline int Max(int x, int y) { return x > y ? x : y; }
    
    const int MN = 100005;
    const int MS = 6200005;
    const int BK = 29;
    
    int N, Q;
    int A[MN];
    int eh[MN], nxt[MN * 2], to[MN * 2], tot;
    inline void insw(int x, int y) {
    	nxt[++tot] = eh[x]; to[tot] = y; eh[x] = tot;
    	nxt[++tot] = eh[y]; to[tot] = x; eh[y] = tot;
    }
    
    int sz[MS], ch[MS][2], cnt;
    int rt1[MN], rt2[MN];
    inline void Ins(int &rt, int x, int j) {
    	ch[++cnt][0] = ch[rt][0], ch[cnt][1] = ch[rt][1], sz[cnt] = sz[rt], rt = cnt;
    	++sz[rt];
    	if (~j) Ins(ch[rt][x >> j & 1], x, j - 1);
    }
    
    int ldf[MN], rdf[MN], dep[MN], faz[MN][17], dfc;
    
    void DFS(int u, int fa) {
    	ldf[u] = ++dfc; faz[u][0] = fa; dep[u] = dep[fa] + 1;
    	Ins(rt1[dfc] = rt1[dfc - 1], A[u], BK);
    	Ins(rt2[u] = rt2[fa], A[u], BK);
    	for (int j = 1; 1 << j < dep[u]; ++j) faz[u][j] = faz[faz[u][j - 1]][j - 1];
    	for (int i = eh[u]; i; i = nxt[i]) if (to[i] != fa) DFS(to[i], u);
    	rdf[u] = dfc;
    }
    
    inline int LCA(int x, int y) {
    	if (dep[x] < dep[y]) x ^= y ^= x ^= y;
    	for (int d = dep[x] - dep[y], j = 0; d; d >>= 1, ++j) if (d & 1) x = faz[x][j];
    	if (x == y) return x;
    	for (int j = 16; ~j; --j) if (faz[x][j] != faz[y][j]) x = faz[x][j], y = faz[y][j];
    	return faz[x][0];
    }
    
    int Qu(int rt1, int rt2, int x, int j) {
    	if (j == -1) return 0;
    	int p = (x >> j & 1) ^ 1;
    	if (sz[ch[rt1][p]] - sz[ch[rt2][p]])
    		return Qu(ch[rt1][p], ch[rt2][p], x, j - 1) | 1 << j;
    	return Qu(ch[rt1][p ^ 1], ch[rt2][p ^ 1], x, j - 1);
    }
    
    int main() {
    	scanf("%d%d", &N, &Q);
    	for (int i = 1; i <= N; ++i)
    		scanf("%d", A + i);
    	for (int i = 1, x, y; i < N; ++i) {
    		scanf("%d%d", &x, &y);
    		insw(x, y);
    	}
    	DFS(1, 0);
    	for (int i = 1, opt, x, y, z; i <= Q; ++i) {
    		scanf("%d", &opt);
    		if (opt == 1) {
    			scanf("%d%d", &x, &z);
    			printf("%d
    ", Qu(rt1[rdf[x]], rt1[ldf[x] - 1], z, BK));
    		}
    		else {
    			scanf("%d%d%d", &x, &y, &z);
    			int w = faz[LCA(x, y)][0];
    			printf("%d
    ", Max(Qu(rt2[x], rt2[w], z, BK), Qu(rt2[y], rt2[w], z, BK)));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    [Luogu 3794]签到题IV
    [JSOI 2015]最大公约数
    [BZOJ 5123][Lydsy1712月赛]线段树的匹配
    [BZOJ 5127][Lydsy1712月赛]数据校验
    [Codeforces Educational Round 71]Div. 2
    [NOIp 2018]all
    [BZOJ 2134]单选错位
    [hihoCoder 1384]Genius ACM
    [POJ 3233]Matrix Power Series
    [USACO 09FEB]Bullcow
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/10171502.html
Copyright © 2020-2023  润新知