zoukankan      html  css  js  c++  java
  • 洛谷P4592 [TJOI2018]异或 【可持久化trie树】

    题目链接

    BZOJ4592

    题解

    可持久化trie树裸题

    写完就A了

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 100005,B = 30,maxm = 5000005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int bin[50];
    struct Trie{
    	int ch[maxm][2],sum[maxm],rt[maxn],cnt;
    	int ins(int pre,int x){
    		int tmp,u;
    		tmp = u = ++cnt;
    		for (int i = B; i >= 0; i--){
    			ch[u][0] = ch[pre][0];
    			ch[u][1] = ch[pre][1];
    			sum[u] = sum[pre] + 1;
    			int t = x & bin[i]; t >>= i;
    			pre = ch[pre][t];
    			u = ch[u][t] = ++cnt;
    		}
    		sum[u] = sum[pre] + 1;
    		return tmp;
    	}
    	int query(int pre,int u,int x,int dep){
    		if (dep < 0) return 0;
    		int t = x & bin[dep]; t >>= dep;
    		if (sum[ch[u][t ^ 1]] - sum[ch[pre][t ^ 1]])
    			return bin[dep] + query(ch[pre][t ^ 1],ch[u][t ^ 1],x,dep - 1);
    		return query(ch[pre][t],ch[u][t],x,dep - 1);
    	}
    	int Query(int a,int b,int c,int d,int x,int dep){
    		if (dep < 0) return 0;
    		int t = x & bin[dep]; t >>= dep;
    		if (sum[ch[a][t ^ 1]] + sum[ch[b][t ^ 1]] - sum[ch[c][t ^ 1]] - sum[ch[d][t ^ 1]])
    			return bin[dep] + Query(ch[a][t ^ 1],ch[b][t ^ 1],ch[c][t ^ 1],ch[d][t ^ 1],x,dep - 1);
    		return Query(ch[a][t],ch[b][t],ch[c][t],ch[d][t],x,dep - 1);
    	}
    }T1,T2;
    int n,Q,val[maxn];
    int h[maxn],ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 1];
    inline void build(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    int dfn[maxn],fa[maxn][18],at[maxn],siz[maxn],dep[maxn],cnt;
    void dfs(int u){
    	dfn[u] = ++cnt; at[cnt] = u; siz[u] = 1;
    	T1.rt[u] = T1.ins(T1.rt[fa[u][0]],val[u]);
    	REP(i,17) fa[u][i] =fa[fa[u][i - 1]][i - 1];
    	Redge(u) if ((to = ed[k].to) != fa[u][0]){
    		fa[to][0] = u; dep[to] = dep[u] + 1; dfs(to);
    		siz[u] += siz[to];
    	}
    }
    int lca(int u,int v){
    	if (dep[u] < dep[v]) swap(u,v);
    	for (int i = 0,d = dep[u] - dep[v]; (1 << i) <= d; i++)
    		if (d & (1 << i)) u = fa[u][i];
    	if (u == v) return u;
    	for (int i = 17; i >= 0; i--)
    		if (fa[u][i] != fa[v][i]){
    			u = fa[u][i];
    			v = fa[v][i];
    		}
    	return fa[u][0];
    }
    int main(){
    	bin[0] = 1; REP(i,30) bin[i] = bin[i - 1] << 1;
    	n = read(); Q = read();
    	REP(i,n) val[i] = read();
    	for (int i = 1; i < n; i++) build(read(),read());
    	dfs(1);
    	for (int i = 1; i <= n; i++)
    		T2.rt[i] = T2.ins(T2.rt[i - 1],val[at[i]]);
    	int opt,x,y,z,o;
    	while (Q--){
    		opt = read(); x = read(); y = read();
    		if (opt & 1){
    			printf("%d
    ",T2.query(T2.rt[dfn[x] - 1],T2.rt[dfn[x] + siz[x] - 1],y,B));
    		}
    		else {
    			z = read(); o = lca(x,y);
    			printf("%d
    ",T1.Query(T1.rt[x],T1.rt[y],T1.rt[o],T1.rt[fa[o][0]],z,B));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    CEAA自动汇编脚本常用命令
    PIC之拉电流和灌电流
    CHARRANGE 结构
    汇编中的lodsb和stosb、lodsd和stosd指令
    汇编中的STOSB与STOSD指令
    汇编中的CLD指令
    SQL中distinct的用法
    SQL union介绍
    【项目排期】测试排期问题思考
    SQL join的介绍
  • 原文地址:https://www.cnblogs.com/Mychael/p/9049815.html
Copyright © 2011-2022 走看看