Loading

可持久化01Tire&DFS序

字典树,前面的AC自动机里面用的东西

\(01Tire\) 可以用来解决 \(xor\) 问题

struct{
    int c[N][2],tot;
    int getnode(){
        tot++;
        c[tot][0] = c[tot][1] = 0;
        return tot;
    }    
    void insert(int val){
	    int u = 0;
	    for(int i = maxbit;i >= 0;i--){
	        int v = (val & (1 << i) ) ? 1 : 0;
	        if(!c[u][v])c[u][v] = getnode();
	        u = c[u][v];
	    }
    }
    void init(){
        c[0][0] = c[0][1] = 0;
    	tot = 0;
   	}
}Tire;

动态开点

int getnode(){
	tot++;
	c[tot][0] = c[tot][1] = 0;
	return tot;
}  

动态开点的好处就是在多数数据的时候不需要 memset

数据插入

void insert(int val){
	int u = 0;
	for(int i = maxbit;i >= 0;i--){
		int v = (val & (1 << i) ) ? 1 : 0;
		if(!c[u][v])c[u][v] = getnode();
		u = c[u][v];
	}
}

从高位到低位插入到01字典树中

01Tire

HDU-4825 Xor Sum

给一个集合,每次询问给出 \(x\) ,输出集合中的数 \(k\) 使得它们异或最大。

注意是输出数,不是输出最大的异或值

思路:

用集合里的数建 \(01Tire\) ,将 \(x\) 按位取反,从高位开始匹配,匹配失败则换一边

#include<bits/stdc++.h>
using namespace std;

const int N = 2e6 + 10;
const int maxbit = 30; //int不能开31,intmax = (1<<31)-1
struct{
    int c[N][2],tot;
    
    int getnode(){
        tot++;
        c[tot][0] = c[tot][1] = 0;
        return tot;
    }    
    void insert(int val){
	    int u = 0;
	    for(int i = maxbit;i >= 0;i--){
	        int v = (val & (1 << i) ) ? 1 : 0;
	        if(!c[u][v])c[u][v] = getnode();
	        u = c[u][v];
	    }
    }

    int query(int val){
        int u = 0;
        int ans = 0;
	    for(int i = maxbit;i >= 0;i--){
	        int v = (val & (1 << i)) ? 0 : 1;
	        if(!c[u][v]) v ^= 1;
	        if(v)ans += (1 << i);
	        
	        u = c[u][v];
	    }
	    return ans;
    }
    void init(){
        c[0][0] = c[0][1] = 0;
    	tot = 0;
   	}
}Tire;

int n,m,x,T;

int main(){
    scanf("%d",&T);
    for(int c = 1;c <= T;c++){
    	Tire.init();
    	scanf("%d%d",&n,&m);
   	 	for(int i = 0;i < n;i++){
   	     	scanf("%d",&x);
   	     	Tire.insert(x);
	   	}
	   	printf("Case #%d:\n",c);
 	   	for(int i = 0;i < m;i++){
        	scanf("%d",&x);
        	printf("%d\n",Tire.query(x));
	   	}
    }
}

可持久化Tire

51nod-1295 XOR key

区间查询

搞一个可持久化的Tire就好了

插入:

// root[i] = insert(root[i-1],v,val);
int insert(int pre, int v, int val) {
	int u = getnode();
	int ans = u;
	for (int i = maxbit; i >= 0; i--) {
		c[u][0] = c[pre][0];
		c[u][1] = c[pre][1]; //复制信息
		int x = val & (1 << i) ? 1 : 0;
		c[u][x] = getnode();//开点
		u = c[u][x]; // 0 是空的节点,所以可以一直这样迭代
		pre = c[pre][x];
	}
	return ans;
}

其实也很简单,就是复制之前的信息,然后开点。

查询:

由于开点是一个一个分配的,所以只要 id < root[l] 就不是区间内

,所以只要加上这一个判断就跟之前的一样。

int query(int l, int r, int x) {
	int MinID = root[l];

	int u = root[r];
	int ans = 0;
	for (int i = maxbit; i >= 0; i--) {
		int now = (x & (1 << i)) ? 0 : 1;
		if (c[u][now] and c[u][now] >= MinID) {
			u = c[u][now];
			ans += (1 << i);
		}
		else {
			u = c[u][now ^ 1];
		}
	}
	return ans;
}

完整代码

/*
 * @Author: zhl
 * @Date: 2020-10-13 09:46:47
 */


 //                            #@@# .   .,,,.                                   
 //                          /@@@@@&             @@@@@&                         
 //                          /@@@@                 @@@@                         
 //                            /%      *(#%,,,,&%, .@@.                         
 //                            (        ./*   ,*.   %                           
 //                           (          *     ,     .                          
 //                          @@        ,.  .,        @@       @@@@,             
 //                         &@@@@.     ., ,.    .  /@@@@@&&&&@@@@@.             
 //                     @@@@@@@@@@@@#*       .,%@@@@@@@@@@@@@@@@@               
 //                  @@@@@@@, @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    
 //          .     @@@@@@     @@@@@@@@@@@@@@@@@@@@@@@@@@%%%&%&&@&%@&            
 //     .  .//,   &@@@@        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%%&&           
 //       (/,,,  *               @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&%%%@@/          
 //   ((*//,,*  #/&#              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%%@@&@@@@@*    
 //    #((###%%%%%#(          .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%&&@@%/@@@@@@   
 //   %####%%%%%%%%%%,*    @@@@@@@@@#                  @@@@@@@@@&&&@@           
 //   ####%%%%%%%%%%/   @@@@@@@,                       @@@@@@@@@@&&@&           
 //  (##((#%%%%%%%%#    &@@.                          @@&...&%@@@@@&&           
 //  /(((##%%%%%%%%                                             @%,             
 //  /((##%%%%%%%%                                                              
 //        ,#%&%#                                                               


#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
#define swap(a,b) a^=b,b^=a,a^=b

const int N = 2e6 + 10;
const int maxbit = 30;
struct {
	int root[N], c[N][2], tot;
	void init() {
		c[0][0] = c[0][1] = 0;
		tot = 0;
		root[0] = 0;
	}
	int getnode() {
		tot++;
		c[tot][0] = c[tot][1] = 0;
		return tot;
	}
	//root[v] = insret(Tire.root[v-1], v, val);
	int insert(int pre, int v, int val) {
		int u = getnode();
		int ans = u;
		for (int i = maxbit; i >= 0; i--) {
			c[u][0] = c[pre][0];
			c[u][1] = c[pre][1];
			int x = val & (1 << i) ? 1 : 0;
			c[u][x] = getnode();
			u = c[u][x];
			pre = c[pre][x];
		}
		return ans;
	}
	int query(int l, int r, int x) {
		int Treesize = maxbit + 2;
		int MinID = root[l];

		int u = root[r];
		int ans = 0;
		for (int i = maxbit; i >= 0; i--) {
			int now = (x & (1 << i)) ? 0 : 1;
			if (c[u][now] and c[u][now] >= MinID) {
				u = c[u][now];
				ans += (1 << i);
			}
			else {
				u = c[u][now ^ 1];
			}
		}
		return ans;
	}
}Tire;

int n, m, l, r, x;
int A[N];
int main() {
	scanf("%d%d", &n, &m);
	Tire.init();
	for (int i = 1; i <= n; i++) {
		scanf("%d", A + i);
		Tire.root[i] = Tire.insert(Tire.root[i-1],i,A[i]);
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &x, &l, &r);
		printf("%d\n", Tire.query(l + 1, r + 1, x));
	}
}

DFS序 + 可持久化Tire

HDU-6191

思路:

DFS序,转化为第二个问题

dfs序:

void dfs(int u, int p) {
	L[u] = ++cnt;
	val[cnt] = A[u];
	repE(i, u) {
		if (E[i].to == p)continue;
		dfs(E[i].to, u);
	}
	R[u] = ++cnt;
	val[cnt] = A[u];
}

完整代码:

/*
 * @Author: zhl
 * @Date: 2020-10-13 11:06:09
 */


 //                            #@@# .   .,,,.                                   
 //                          /@@@@@&             @@@@@&                         
 //                          /@@@@                 @@@@                         
 //                            /%      *(#%,,,,&%, .@@.                         
 //                            (        ./*   ,*.   %                           
 //                           (          *     ,     .                          
 //                          @@        ,.  .,        @@       @@@@,             
 //                         &@@@@.     ., ,.    .  /@@@@@&&&&@@@@@.             
 //                     @@@@@@@@@@@@#*       .,%@@@@@@@@@@@@@@@@@               
 //                  @@@@@@@, @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    
 //          .     @@@@@@     @@@@@@@@@@@@@@@@@@@@@@@@@@%%%&%&&@&%@&            
 //     .  .//,   &@@@@        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%%&&           
 //       (/,,,  *               @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&%%%@@/          
 //   ((*//,,*  #/&#              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%%@@&@@@@@*    
 //    #((###%%%%%#(          .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%&&@@%/@@@@@@   
 //   %####%%%%%%%%%%,*    @@@@@@@@@#                  @@@@@@@@@&&&@@           
 //   ####%%%%%%%%%%/   @@@@@@@,                       @@@@@@@@@@&&@&           
 //  (##((#%%%%%%%%#    &@@.                          @@&...&%@@@@@&&           
 //  /(((##%%%%%%%%                                             @%,             
 //  /((##%%%%%%%%                                                              
 //        ,#%&%#                                                               


#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
#define swap(a,b) a^=b,b^=a,a^=b

const int N = 2e5 + 10;
//cnm 1e6 一直T
//N 5e5,m 5e5

struct Edge {
	int to, next;
}E[N << 1];

int head[N], tot;
void addEdge(int from, int to) {
	E[++tot] = Edge{ to,head[from] };
	head[from] = tot++;
}

const int maxbit = 30;
struct {
	int root[N<<5], c[N<<5][2], tot;
	void init() {
		c[0][0] = c[0][1] = 0;
		tot = 0;
		root[0] = 0;
	}
	int getnode() {
		tot++;
		c[tot][0] = c[tot][1] = 0;
		return tot;
	}
	//root[v] = insret(Tire.root[v-1], v, val);
	int insert(int pre, int v, int val) {
		int u = getnode();
		int ans = u;
		for (int i = maxbit; i >= 0; i--) {
			c[u][0] = c[pre][0];
			c[u][1] = c[pre][1];
			int x = val & (1 << i) ? 1 : 0;
			c[u][x] = getnode();
			u = c[u][x];
			pre = c[pre][x];
		}
		return ans;
	}
	int query(int l, int r, int x) {
		int Treesize = maxbit + 2;
		int MinID = root[r] - Treesize * (r - l);

		int u = root[r];
		int ans = 0;
		for (int i = maxbit; i >= 0; i--) {
			int now = (x & (1 << i)) ? 0 : 1;
			if (c[u][now] and c[u][now] >= MinID) {
				u = c[u][now];
				ans += (1 << i);
			}
			else {
				u = c[u][now ^ 1];
			}
		}
		return ans;
	}
}Tire;

int n, q, l, r, x;
int A[N];

int cnt;
int val[N << 1], L[N], R[N];
void dfs(int u, int p) {
	L[u] = ++cnt;
	val[cnt] = A[u];
	repE(i, u) {
		if (E[i].to == p)continue;
		dfs(E[i].to, u);
	}
	R[u] = ++cnt;
	val[cnt] = A[u];
}
int main() {
	while (scanf("%d%d", &n, &q) == 2) {
		memset(head, 0, sizeof(int) * (n + 10));
		tot = 0; Tire.init();

		for (int i = 1; i <= n; i++) {
			scanf("%d", A + i);
		}

		for (int i = 1; i < n; i++) {
			scanf("%d", &l);
			addEdge(l, i + 1);
			addEdge(i + 1, l);
		}

		cnt = 0;
		dfs(1, -1);

		for (int i = 1; i <= cnt; i++) {
			Tire.root[i] = Tire.insert(Tire.root[i - 1], i, val[i]);
		}

		for (int i = 0; i < q; i++) {
			scanf("%d%d", &l, &x);
			printf("%d\n", Tire.query(L[l], R[l], x));
		}
	}
}

LCA + 可持久化Tire

洛谷异或

两种询问,

1 x z,询问 x 的子树与 z 异或的最大值

2 x y z,询问路径与 z 异或的最大值

思路:

建两颗可持久化Tire,一颗按dfs顺序建,一颗每个点接到它的父节点,也是树型结构。

void dfs(int u, int p) {
	id[u] = ++cnt;
	fa[u][0] = p; dep[u] = dep[p] + 1;

	for (int x = 1; (1 << x) < dep[u]; x++) {
		fa[u][x] = fa[fa[u][x - 1]][x - 1];
	}

	Tire1.root[cnt] = Tire1.insert(Tire1.root[cnt - 1], A[u]);
	Tire2.root[cnt] = Tire2.insert(Tire2.root[id[p]], A[u]);
	sz[u] = 1;
	repE(i, u) {
		int v = E[i].to;
		if (v == p)continue;
		dfs(v, u);

		sz[u] += sz[v];
	}
}

完整代码

/*
 * @Author: zhl
 * @Date: 2020-10-14 10:12:23
 */
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
using namespace std;
const int N = 5e5 + 10;

struct Edge {
	int to, next;
}E[N << 1];

int head[N], tot;
void addEdge(int from, int to) {
	E[++tot] = Edge{ to,head[from] };
	head[from] = tot++;
}

int A[N];

int n, m;
const int maxbit = 30;
struct {
	int c[N << 5][2], root[N], tot;
	int getnode() {
		tot++;
		c[tot][0] = c[tot][1] = 0;
		return tot;
	}
	void init() {
		c[0][0] = c[0][1] = 0;
		tot = 0;
	}
	int insert(int pre, int val) {
		int u = getnode();
		int ans = u;
		for (int i = maxbit; i >= 0; i--) {
			c[u][0] = c[pre][0];
			c[u][1] = c[pre][1];
			int x = val & (1 << i) ? 1 : 0;
			c[u][x] = getnode();
			u = c[u][x];
			pre = c[pre][x];
		}
		return ans;
	}
	int query(int l, int r, int val) {
		int minID = root[l];
		int u = root[r];
		int ans = 0;
		for (int i = maxbit; i >= 0; i--) {
			int now = (val & (1 << i)) ? 0 : 1;
			if (c[u][now] and c[u][now] >= minID) {
				ans += (1 << i);
				u = c[u][now];
			}
			else u = c[u][now ^ 1];
		}
		return ans;
	}
}Tire1, Tire2;

int sz[N], id[N], cnt, fa[N][32], dep[N];
void dfs(int u, int p) {
	id[u] = ++cnt;
	fa[u][0] = p; dep[u] = dep[p] + 1;

	for (int x = 1; (1 << x) < dep[u]; x++) {
		fa[u][x] = fa[fa[u][x - 1]][x - 1];
	}

	Tire1.root[cnt] = Tire1.insert(Tire1.root[cnt - 1], A[u]);
	Tire2.root[cnt] = Tire2.insert(Tire2.root[id[p]], A[u]);
	sz[u] = 1;
	repE(i, u) {
		int v = E[i].to;
		if (v == p)continue;
		dfs(v, u);

		sz[u] += sz[v];
	}
}

int LCA(int x, int y) {
	if (dep[x] < dep[y])swap(x, y);
	while (dep[x] != dep[y]) {
		int u = dep[x] - dep[y];
		int v = 0;
		while (!(u & (1 << v)))v++;
		x = fa[x][v];
	}

	while (x != y) {
		int v = 0;
		while (fa[x][v] != fa[y][v])v++;
		x = fa[x][max(0, v - 1)]; y = fa[y][max(0, v - 1)];
	}
	return x;
}

int main() {
	scanf("%d%d", &n, &m);
	rep(i, 1, n)scanf("%d", A + i);
	rep(i, 1, n - 1) {
		int x, y; scanf("%d%d", &x, &y);
		addEdge(x, y); addEdge(y, x);
	}
	dfs(1, 0);
	rep(i, 1, m) {
		int op, a, b, x; scanf("%d", &op);
		if (op == 1) {
			scanf("%d%d", &a, &x);
			printf("%d\n", Tire1.query(id[a], id[a] + sz[a] - 1, x));
		}
		else {
			scanf("%d%d%d", &a, &b, &x);
			int u = LCA(a, b);
			printf("%d\n", max(Tire2.query(id[u], id[a], x), Tire2.query(id[u], id[b], x)));
		}
	}
}

HDU-4757 Tree

路径查询

/*
 * @Author: zhl
 * @Date: 2020-10-14 10:12:23
 */
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
using namespace std;
const int N = 2e5 + 10;

struct Edge {
	int to, next;
}E[N << 1];

int head[N], tot;
void addEdge(int from, int to) {
	E[++tot] = Edge{ to,head[from] };
	head[from] = tot++;
}

int A[N];

int n, m;
const int maxbit = 30;
struct {
	int c[N << 5][2], root[N], tot;
	int getnode() {
		tot++;
		c[tot][0] = c[tot][1] = 0;
		return tot;
	}
	void init() {
		c[0][0] = c[0][1] = 0;
		tot = 0;
	}
	int insert(int pre, int val) {
		int u = getnode();
		int ans = u;
		for (int i = maxbit; i >= 0; i--) {
			c[u][0] = c[pre][0];
			c[u][1] = c[pre][1];
			int x = val & (1 << i) ? 1 : 0;
			c[u][x] = getnode();
			u = c[u][x];
			pre = c[pre][x];
		}
		return ans;
	}
	int query(int l, int r, int val) {
		int minID = root[l];
		int u = root[r];
		int ans = 0;
		for (int i = maxbit; i >= 0; i--) {
			int now = (val & (1 << i)) ? 0 : 1;
			if (c[u][now] and c[u][now] >= minID) {
				ans += (1 << i);
				u = c[u][now];
			}
			else u = c[u][now ^ 1];
		}
		return ans;
	}
}Tire;

int sz[N], id[N], cnt, fa[N][32], dep[N];
void dfs(int u, int p) {
	id[u] = ++cnt;
	fa[u][0] = p; dep[u] = dep[p] + 1;
	sz[u] = 1;
	for (int x = 1; (1 << x) < dep[u]; x++) {
		fa[u][x] = fa[fa[u][x - 1]][x - 1];
	}

	Tire.root[cnt] = Tire.insert(Tire.root[id[p]], A[u]);

	repE(i, u) {
		int v = E[i].to;
		if (v == p)continue;
		dfs(v, u);

		sz[u] += sz[v];
	}
}

int LCA(int x, int y) {
	if (dep[x] < dep[y])swap(x, y);
	while (dep[x] != dep[y]) {
		int u = dep[x] - dep[y];
		int v = 0;
		while (!(u & (1 << v)))v++;
		x = fa[x][v];
	}

	while (x != y) {
		int v = 0;
		while (fa[x][v] != fa[y][v])v++;
		x = fa[x][max(0, v - 1)]; y = fa[y][max(0, v - 1)];
	}
	return x;
}

int main() {
	while (~scanf("%d%d", &n, &m)) {
		Tire.init();
		tot = 0;
		cnt = 0;
		rep(i, 1, n) {
			head[i] = 0;
			memset(fa[i], 0, sizeof(fa[i]));
		}
		rep(i, 1, n)scanf("%d", A + i);
		rep(i, 1, n - 1) {
			int x, y; scanf("%d%d", &x, &y);
			addEdge(x, y); addEdge(y, x);
		}
		dfs(1, 0);
		rep(i, 1, m) {
			int a, b, x;
			scanf("%d%d%d", &a, &b, &x);
			int u = LCA(a, b);
			printf("%d\n", max(Tire.query(id[u], id[a], x), Tire.query(id[u], id[b], x)));
		}
	}
}
posted @ 2020-10-13 16:51  —O0oO-  阅读(129)  评论(0编辑  收藏  举报