首页 > 其他分享 >两道神奇的字典树

两道神奇的字典树

时间:2024-03-21 20:23:02浏览次数:18  
标签:int res resnow mid long text 字典 两道 神奇

AEC122D

题意:你现在有 \(2N\) 个球,现在 A 和 B 轮流拿,设每一次拿到两个球的权值的异或为 \(p_i\),定义分数为 \(\max \{ p_i\}\)。A 希望它大,B 希望它小。求最后的分数。

题解:首先,B 有绝对优势,B 先把它们两两分组,A 拿走了一个时,B 直接拿走与它同组的那个。所以现在题目变为求每一组的异或的最小值。

现在把他们插入到字典树上。定义二进制 \(i\) 位为 \(v\) 的集合为 \(S_v\)。\((v = \{0, 1 \})\)。定义 \(S = S_0 \cup S_1\)。(这里省略了 \(i\),下同)

现在已知 \(|S|=2n \in \text{even}\)。所以 \(S_0\) 和 \(S_1\) 同奇偶。考虑按位贪心。

若它们都是偶数,那么这一位为 \(0\),否则不优。递归为两个子问题。

否则,这一位无论如何我都为 \(1\),那么第 \(i\) 位以后的贡献为:

\[\mathop{\max}_{i \in S_0, j \in S_1} \{a_i \oplus a_j\} \]

用字典树维护即可。

AEC122D 的神奇加强版

题意:你现在有 \(2N + 1\) 个球,提前拿出一个球 \(k\)。现在 A 和 B 轮流拿,设每一次拿到两个球的权值的异或为 \(p_i\),定义分数为 \(\max \{ p_i\}\)。A 希望它大,B 希望它小。求每个 \(k\) 最后的分数。对于所有数据,保证 \(1\le n\le 2×10^5,0\le a_i < 2^{30}\)。时间 \(1\) 秒,空间 \(64 \space \text{MiB}\)。

同时维护 \(2N+1\) 个数。则 \(|S|=2n \in \text{odd}\)。考虑当前状态下删掉 \(k\) 这个球对第 \(k\) 个答案的贡献

那么,设 \(O = (S_0 \cup \text{odd}) \cap (S_1 \cup \text{odd})\)。\(E = (S_0 \cup \text{even}) \cap (S_1 \cup \text{even})\)。

当 \(k \in O\) 时,两个都变成了偶数,此时奇数那一组就变成一个子问题,但是需要求解偶数那一组的答案,对奇数组的答案进行更新。

当 \(k \in E\) 时,就变为两组奇数个,把奇数那一组插入 Trie,然后只需枚举偶数那一组的每个数,求出最小的配对之后取最小值或者次小值即可。

具体的,出题人比较卡时间或空间。考验良好的代码习惯。我是不用卡的,算法过了就过了。

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

const int N = 4e5 + 5;

int n, dl, dr, midtmp, ls[10000005], rs[10000005], totcnt, u2;
long long ans1[N], ans2[N], resnow, now, tmp;
pair<int, int> a[N];
struct tri{long long fir, sec; int pos;}res, tmp2;

tri calXor(long long k, int l1, int r1, int l2, int r2, int u){
	res.fir = 1e18, res.sec = 1e18, res.pos = 0;
	for(int i = l1; i <= r1; i++){
		dl = l2, dr = r2, resnow = 0, u2 = u;
		for(int j = k; j >= 0; j--){
			now = (a[i].first >> j) & 1;
			if(!now && !ls[u2]) resnow += (1 << j), u2 = rs[u2];
			else if(!now) u2 = ls[u2];
			if(now && !rs[u2]) resnow += (1 << j), u2 = ls[u2];
			else if(now) u2 = rs[u2];
		}
		if(resnow <= res.fir)
			res.sec = res.fir, res.fir = resnow, res.pos = i;
		else if(res.sec >= resnow && resnow > res.fir)
			res.sec = resnow;
		resnow = 0;
	}
	return res;
}

long long calEven(long long k, int l, int r, int u){
	if(k < 0 || r - l + 1 <= 0) return 0;
	int mid = l;
	while(mid <= r && ((a[mid].first >> k) & 1) == 0) mid++;
	mid--;
	if((l - mid + 1) & 1) return (1 << k) + calXor(k - 1, l, mid, mid + 1, r, rs[u]).fir;
	return max(calEven(k - 1, l, mid, ls[u]), calEven(k - 1, mid + 1, r, rs[u]));
}

void calOdd(long long k, int l, int r, int u){
	if(k < 0 || (r - l + 1) < 0) return ;
	int mid = l;
	while(mid <= r && ((a[mid].first >> k) & 1) == 0) mid++;
	mid--;
	if((mid - l + 1) & 1){
		tmp = calEven(k - 1, mid + 1, r, rs[u]);
		for(int i = l; i <= mid; i++) ans2[i] = max(ans2[i], tmp);
		tmp2 = calXor(k - 1, mid + 1, r, l, mid, ls[u]);
		for(int i = mid + 1; i <= r; i++) ans1[i] += (1 << k);
		for(int i = mid + 1; i <= r; i++){
			if(i == tmp2.pos) ans1[i] += tmp2.sec;
			else ans1[i] += tmp2.fir;
		}
		
		calOdd(k - 1, l, mid, ls[u]);
	}
	else{
		tmp = calEven(k - 1, l, mid, ls[u]);
		for(int i = mid + 1; i <= r; i++) ans2[i] = max(ans2[i], tmp);
		tmp2 = calXor(k - 1, l, mid, mid + 1, r, rs[u]);
		for(int i = l; i <= mid; i++) ans1[i] += (1 << k);
		for(int i = l; i <= mid; i++){
			if(i == tmp2.pos) ans1[i] += tmp2.sec;
			else ans1[i] += tmp2.fir;
		}
		
		calOdd(k - 1, mid + 1, r, rs[u]);
	}
	return ;
}

void init(int l, int r, int k, int u){
	if(k < 0) return ;
	int mid = l;
	while(mid <= r && ((a[mid].first >> k) & 1) == 0) mid++;
	mid--;
	if(l <= mid) ls[u] = ++totcnt, init(l, mid, k - 1, totcnt);
	if(mid + 1 <= r) rs[u] = ++totcnt, init(mid + 1, r, k - 1, totcnt);
	return ;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n;
	n = 2 * n + 1;
	for(int i = 1; i <= n; i++) cin >> a[i].first, a[i].second = i;
	sort(a + 1, a + 1 + n);
	
	totcnt = 1, init(1, n, 29, 1);
	calOdd(29, 1, n, 1);
	
	for(int i = 1; i <= n; i++) a[a[i].second].first = max(ans1[i], ans2[i]);
	for(int i = 1; i <= n; i++) cout << a[i].first << " ";
	return 0;
}

标签:int,res,resnow,mid,long,text,字典,两道,神奇
From: https://www.cnblogs.com/lc0802/p/18088176

相关文章

  • B树B+树,字典树详解,哈夫曼树博弈树
    目录B树:B-TreeB+树字典树:TrieTree 哈夫曼树博弈树B树:B-Tree多路平衡搜索树1.M阶B树,就是M叉(M个指针)。2.每个节点内记录个数<=M-1。3.根节点记录个数>=1。4.其余节点内记录个数>=ceil(m/2)-1(向上取整)。5.每个节点内的记录从左至右从大到小有序。6.当前记录的左......
  • 探秘电路世界的魔法!解析电路仿真软件的奥秘与神奇功能
    在当今电子科技高速发展的时代,电路设计已经成为了许多领域的重要组成部分。而在电路设计的过程中,电路仿真软件无疑是不可或缺的工具之一。今天,让我们一起来揭开电路仿真软件的神秘面纱,探索其中的奥秘与神奇功能!了解电路仿真软件的基本原理和功能电路仿真软件是通过数学模型......
  • B3927 [GESP202312 四级]小杨的字典(入门小白版)
    本题包括:1.简单的map使用2.字符串简单处理本题参考洛谷题解: https://www.luogu.com.cn/problem/solution/B3927难度:普及-对于笔者而言:不会用map,在b站和csdn上搜map的使用方法,只能说是杂而乱杂在于:介绍的种类方法多种多样,但是底下的使用方法寥寥无几,与开头的介绍有......
  • pymatting,一个神奇的 Python 库!
    更多资料获取......
  • six,一个神奇的 Python 版本兼容工具库!
    目录前言什么是Pythonsix库?核心功能使用方法 1.安装six库 2.导入six库 3.使用兼容性函数实际应用场景 1.代码库维护 2.项目迁移和重构 3.兼容性包装器总结前言大家好,今天为大家分享一个神奇的Python库-six。Github地址:https://github......
  • 单调队列 维护区间最值(板子+两道练手)
    1.P1886滑动窗口/【模板】单调队列https://www.luogu.com.cn/problem/P1886板子题,传送门在上方//Problem://P1886滑动窗口/【模板】单调队列////Contest:Luogu//URL:https://www.luogu.com.cn/problem/P1886//MemoryLimit:500MB//TimeLimit:1......
  • python疑难杂症(9)---python的数据类型字典(dict)的创建、访问、修改、删除等方法汇总
    在Python中,字典(Dictionary)是一种内置的数据烈性,是无序的数据结构,用于存储键值对(key-value)。字典中的每个元素由一个键(key)和一个对应的值(value)组成,键和值之间使用冒号(:)进行分隔,每个键值对之间使用逗号(,)进行分隔。字典中的键必须是唯一的,而值可以是任意类型的对象,字典可以用来存......
  • 【Oracle】数据字典dba_tables
    视图dba_tables是数据库中所有数据表的描述。该视图包含的列属性还是非常多个,需要慢慢品味。查看视图如下:sys@PDB1>descdba_tables;NameNull?Type 描述------------------------------------------......
  • 列表与字典
    字典:#遍历字典内容1class1={'丁一':85,'王二':95,'张三':75,'李四':65,'赵五':55}foriinclass1:#这个i代表的是字典中的键,也就是丁一、王二麻子等print('class1:',i,class1[i]) #遍历字典内容2class1={'丁一':85,......
  • C# 哈希表Hashtable与字典表Dictionary<K,V>的比较。
    原文链接:https://blog.csdn.net/heyuchang666/article/details/50503240?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-50503240-blog-104036330.235%5Ev43%5Epc_blog_bottom_relevance_base4&depth_1-u......