HDU多校第五场 1002 three arrays —— 01字典树 | 第九场 1008 Rikka with Stable Marriage

HDU多校第五场 1002 three arrays

题目链接:点我啊╭(╯^╰)╮

题目大意:

    两个序列,可以任意调换位置
    求相同位置异或后产生的字典序最小序列

解题思路:

    建两颗 01 01 字典树,然后同时 DFS
    优先走相同边,然后走不同边
    最后得到的答案排序后就是最小序列

核心:01字典树 dfs

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef unsigned long long ll;
typedef pair <int,int> pii;
const int maxn = 1e5 + 10;
int T, n;
vector <pii> ans;
struct Trie{
	static const int maxt = 1e7+5;
	int rt, id, tot, t[maxt][2];
	int cnt[maxt], val[maxt], end[maxt];
	inline int newnode(){
		++tot;
		t[tot][0] = t[tot][1] = 0;
		cnt[tot] = end[tot] = val[tot] = 0;
		return tot;
	}
	inline void init(){
		tot = 0;
		rt = newnode();
	}
	inline void add(int x){
		rt = 1;
		for(int i=31; ~i; i--){
			id = x >> i & 1;
			if(!t[rt][id]) t[rt][id] = newnode();
			rt = t[rt][id];
			++cnt[rt];
		}
		end[rt] = 1, val[rt] = x;
	}
	inline int query(int x){
		rt = 1;
		for(int i=31; ~i; i--){
			id = x >> i & 1;
			if(t[rt][id^1]) rt = t[rt][id^1];
			else rt = t[rt][id];
		}
		return x ^ val[rt];
	}
} A, B;

void dfs(int p1, int p2, int x){
	int num = min(A.cnt[p1], B.cnt[p2]);
	A.cnt[p1] -= num, B.cnt[p2] -= num;
	if(A.end[p1]){
		ans.push_back({x, num});
		return ;
	}
	if(A.cnt[A.t[p1][0]] && B.cnt[B.t[p2][0]]) 
		dfs(A.t[p1][0], B.t[p2][0], x<<1);
		
	if(A.cnt[A.t[p1][1]] && B.cnt[B.t[p2][1]]) 
		dfs(A.t[p1][1], B.t[p2][1], x<<1);
		
	if(A.cnt[A.t[p1][0]] && B.cnt[B.t[p2][1]]) 
		dfs(A.t[p1][0], B.t[p2][1], x<<1|1);
		
	if(A.cnt[A.t[p1][1]] && B.cnt[B.t[p2][0]]) 
		dfs(A.t[p1][1], B.t[p2][0], x<<1|1);
}

int main() {
	scanf("%d", &T);
	while(T--){
		scanf("%d", &n);
		ans.clear();
		A.init(), B.init();
		for(int i=0, tmp; i<n; i++){
			scanf("%d", &tmp);
			A.add(tmp);
		}
		for(int i=0, tmp; i<n; i++){
			scanf("%d", &tmp);
			B.add(tmp);
		}
		dfs(1, 1, 0);
		sort(ans.begin(), ans.end());
		for(int i=0; i<ans.size(); i++)
			for(int j=0; j<ans[i].second; j++){
				printf("%d", ans[i].first);
				printf("%c", i==ans.size()-1&&j==ans[i].second-1 ? '\n' : ' ');
			}
	}
}

第九场 1008 Rikka with Stable Marriage

题目链接:点我啊╭(╯^╰)╮

题目大意:

    两个序列,可以任意调换位置
    求相同位置异或后产生的字典序最大序列

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
int T, n;
ll ans;

struct Trie{
	static const int maxt = 1e7 + 5;
	int rt, id, tot, t[maxt][2];
	int cnt[maxt], val[maxt], end[maxt];
	int newnode(){
		t[++tot][0] = t[tot][1] = 0;
		cnt[tot] = end[tot] = val[tot] = 0;
		return tot;
	}
	void init(){
		tot = 0;
		rt = newnode();
	}
	void add(int x){
		rt = 1;
		for(int i=31; ~i; i--){
			id = x >> i & 1;
			if(!t[rt][id]) t[rt][id] = newnode();
			rt = t[rt][id];
			++cnt[rt];
		}
		end[rt] = 1, val[rt] = x;
	}
} A, B; 

void dfs(int p1, int p2, int x){
	int num = min(A.cnt[p1], B.cnt[p2]);
	A.cnt[p1] -= num, B.cnt[p2] -= num;
	if(A.end[p1]){
		ans += A.val[p1] ^ B.val[p2];
		return;
	}
	if(A.cnt[ A.t[p1][0] ] && B.cnt[ B.t[p2][1] ])
		dfs(A.t[p1][0], B.t[p2][1], x<<1);
		
	if(A.cnt[ A.t[p1][1] ] && B.cnt[ B.t[p2][0] ])
		dfs(A.t[p1][1], B.t[p2][0], x<<1);
		
	if(A.cnt[ A.t[p1][0] ] && B.cnt[ B.t[p2][0] ])
		dfs(A.t[p1][0], B.t[p2][0], x<<1);
		
	if(A.cnt[ A.t[p1][1] ] && B.cnt[ B.t[p2][1] ])
		dfs(A.t[p1][1], B.t[p2][1], x<<1);
}

int main() {
	scanf("%d", &T);
	while(T--){
		A.init(), B.init();
		scanf("%d", &n);
		for(int i=1, x; i<=n; i++) scanf("%d", &x), A.add(x);
		for(int i=1, x; i<=n; i++) scanf("%d", &x), B.add(x);
		ans = 0;
		dfs(1, 1, 0);
		printf("%lld\n", ans);
	}
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Scar_Halo/article/details/102990441