P3765 总统选举

看到了第一篇题解,我懂了随机化的艺术。

确实,这种区间众数用随机化的错误概率很小,并且也快,那我就是用这种方法的。

显然我们知道区间众数是区间中某个数出现次数 >> 区间的一半,那么我们考虑每一次随机抽不中的可能是 12\frac{1}{2},选 kk 次抽不中的概率是 12k\frac{1}{2^k},将 kk 设为 2020,每次选出的数用平衡树统计次数。跟第一篇题解一样,我用的 pbds 的红黑树,pbdssplay 会被卡。

代码:

/*
* author: happybob
* date: 2022/3/20
* 10.34s /  63.41MB /  1.22KB C++20
* https://www.luogu.com.cn/record/71948451
*/

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;

constexpr int N(5e5 + 5), t(20);
tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> tr[N];
int n, m, a[N];

inline int getmax(int l, int r)
{
	for (register int i(1); i <= t; i++)
	{
		int place(l + rand() % (r - l + 1));
		if (tr[a[place]].order_of_key(r + 1) - tr[a[place]].order_of_key(l) > (r - l + 1) >> 1)
		{
			return a[place];
		}
	}
	return -1;
}

int main()
{
	srand(time(NULL));
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
		tr[a[i]].insert(i);
	}
	while (m--)
	{
		int l, r, s;
		scanf("%d%d%d", &l, &r, &s);
		int g(getmax(l, r));
		if (g == -1)
		{
			printf("%d\n", s);
			g = s;
		}
		else
		{
			printf("%d\n", g);
		}
		int k;
		scanf("%d", &k);
		for (int i(1); i <= k; ++i)
		{
			int x;
			scanf("%d", &x);
			tr[a[x]].erase(x);
			a[x] = g;
			tr[a[x]].insert(x);
		}
	}
	int l(1), r(n), s;
	int g(getmax(l, r));
	if (g == -1)
	{
		printf("%d\n", -1);
	}
	else
	{
		printf("%d\n", g);
	}
	return 0;
}
posted @   HappyBobb  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示