20231110

发布时间 2023-11-10 21:59:21作者: ヤ﹎句号悠灬

2023/11/10

字典树学习.2

最大异或对 (Trie)

找出两个数异或起来的最大值 O(n loga[n]),思路就是贪心的优先把高位置为1,然后在Trie树上查找是否有符合的数

const int N = 1e5 + 10;
const int M = 3e6 + 10;
int n, idx;
int a[N];
int son[M][2];

void insert(int x)  //把所有数字先加入Trie里面(建树)
{
	int p = 0;
	for (int i = 32; i >= 0; i--)
	{
		int id = ((x >> i) & 1);
		if (!son[p][id])
		{
			son[p][id] = ++idx;
		}
		p = son[p][id];
	}
}

int query(int x)
{
	int p = 0, res = 0;
	for (int i = 32; i >= 0; i--)
	{
		int id = ((x >> i) & 1);
		if (son[p][!id])
		{
			res += (1LL << i);
			p = son[p][!id];
		}
		else
			p = son[p][id];
	}
	return res;
}
void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		insert(a[i]);
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		ans = max(ans, query(a[i]));
	}
	cout << ans << endl;
}

字典树学到最大异或对就可以补昨天的题了

D - XOR Construction

题意:给n-1个数,构造一个n个数的序列,两两异或起来为给定的序列,构造的数是0~n-1的排列。

思路:如果找异或规律的话,只能构造出奇数的情况,所以考虑一般做法。

我们枚举b1,那么通过a的前缀异或和可以知道其他的数,把a的前缀异或和存到字典树中,然后用这棵树对枚举的每个b求最大异或对,若值为n-1(b的上限),意思为b1为这个数的时候,其他的数的最大值为n-1,刚好符合上限,且题目保证一定可以构造出。那么有鸽巢原理,当前的b1就是答案。如果不存在,那么说明b1就是n-1.

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 2e5 + 10;
const int M = 3e6 + 10;
int n, idx;
int a[N];
int son[M][2];
int b[N];
void insert(int x)
{
	int p = 0;
	for (int i = 30; i >= 0; i--)
	{
		int id = ((x >> i) & 1);
		if (!son[p][id])
		{
			son[p][id] = ++idx;
		}
		p = son[p][id];
	}
}

int query(int x)
{
	int res = 0, p = 0;
	for (int i = 30; i >= 0; i--)
	{
		int id = ((x >> i) & 1);
		if (son[p][!id])
		{
			res += (1LL << i);
			p = son[p][!id];
		}
		else
			p = son[p][id];
	}
	return res;
}

void solve()
{
	cin >> n;
	int res = 0;
	for (int i = 1; i <= n - 1; i++)
	{
		cin >> a[i];
		res ^= a[i];
		insert(res);
		// cerr << res << endl;
	}
	b[1] = n - 1;
	for (int i = 0; i <= n - 1; i++)
	{
		// cerr << query(i) << endl;
		if (query(i) == n - 1)
		{
			b[1] = i;
			break;
		}
	}
	for (int i = 2; i <= n; i++)
	{
		b[i] = a[i - 1] ^ b[i - 1];
	}
	for (int i = 1; i <= n; i++)
	{
		cout << b[i] << " ";
	}
}

signed main()
{
	Acode;
	int T = 1;
	while (T--)
	{
		solve();
	}
	return 0;
}

CF1864D Matrix Cascade

思维题:如果暴力操作的话复杂度是O(n^3)的,想着降一个n

思路:我们从上到下,从左到右的扫描每一个点,这样可以保证被扫描过的点一定是0.然后对于扫到的点是1的情况,那个我们只考虑他这个点对下一层的影响,就是不把他的贡献走完,而是只走一层。这样的好处是可以累加的处理贡献。所以对于一个点,我们维护三个东西,是否是最左边的点,是否是最右边的点,普通向下的点。这样枚举O(n^2),转移O(1),可以通过本题

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 2e5 + 10;
const int M = 3e6 + 10;
int n, idx;
int mp[3010][3010];
int vis[3010][3010][4];
void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			char ch;
			cin >> ch;
			// cin >> mp[i][j];
			mp[i][j] = ch - '0';
			vis[i][j][1] = vis[i][j][2] = vis[i][j][3] = 0;
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			mp[i][j] += vis[i][j][1] + vis[i][j][2] + vis[i][j][3];
			if (mp[i][j] & 1)
			{
				// cerr << i << " " << j << " " << mp[i][j] << endl;
				ans++;
				mp[i][j]++;
				if (j - 1 >= 1)
					vis[i + 1][j - 1][2]++;
				if (j + 1 <= n)
					vis[i + 1][j + 1][3]++;
				vis[i + 1][j][1]++;
			}
			if (vis[i][j][1])
			{
				vis[i + 1][j][1] += vis[i][j][1];
			}
			if (vis[i][j][2])
			{
				if (j - 1 >= 1)
					vis[i + 1][j - 1][2] += vis[i][j][2];
				vis[i + 1][j][1] += vis[i][j][2];
			}
			if (vis[i][j][3])
			{
				if (j + 1 <= n)
					vis[i + 1][j + 1][3] += vis[i][j][3];
				vis[i + 1][j][1] += vis[i][j][3];
			}
		}
	}

	// for (int i = 1; i <= n; i++)
	// {
	// 	for (int j = 1; j <= n; j++)
	// 	{
	// 		cout << mp[i][j] << ' ';
	// 	}
	// 	cout << endl;
	// }
	cout << ans << endl;
}

signed main()
{
	Acode;
	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}
	return 0;
}

今晚补题补的有点慢的,一个上午就学了字典树和补了一道相关的,下午体育课结束后就写了一题(输)

晚上vp div2 还是3题,D题真的只会暴力,想不到其他的任何做法,还得多练

Codeforces Round 906 (Div. 2) solve(3/7)

https://www.bilibili.com/video/BV1Su4y1t7zm/?vd_source=7b3be65640481106bef731ef741a960f

看了D,E1的题解感觉可补,明天早上早点起来补一补