SP7691 HOMO - Homo or Hetero

题意

动态维护一个序列,判断序列是否有两个以上不同的元素以及两个及以上相同的元素。

解法

这题 SPOJ 给出来源是 ACM ICPC 2009–2010, NEERC, Northern Subregional Contest,但是难度并不大,显然 STL 做这道题很容易,这里提供一个平衡树的做法。

显然,判断是否有两个及以上相同的元素,就是判断平衡树里面是否有一个结点的 cnt 是大于等于 22 的。暴力枚举每一个点显然不合适,考虑对于每一个点再维护一个 bool 变量,表示以这个结点为根的子树里是否有两个及以上相同的元素,把这个信息每次都 pushup,只需要判断根节点的这个变量的值即可。

判断是否有两个以上不同的元素,直接 set 即可。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <set>
#include <string>
#include <unordered_map>
using namespace std;

int n, cnt = 0;
set<int> st;
unordered_map<int, int> times;

const int N = 1e5 + 5, INF = INT_MAX;

class Treap
{
public:
	int idx, root;
	struct Node
	{
		int l, r, val, key;
		int sz, cnt;
		bool is_homogeneous;
		//Node(int _l, int _r, int _val, int _key, int _sz, int _cnt, bool _p): l(_l), r(_r), val(_val), key(_key), sz(_sz), cnt(_cnt), is_homogeneous(_p){}
	}tr[N];
	int get_node(int key)
	{
		tr[++idx].key = key;
		tr[idx].sz = tr[idx].cnt = 1;
		tr[idx].val = rand();
		tr[idx].is_homogeneous = false;
		return idx;
	}
	void pushup(int u)
	{
		tr[u].sz = tr[tr[u].l].sz + tr[tr[u].r].sz + tr[u].cnt;
		tr[u].is_homogeneous = tr[tr[u].l].is_homogeneous || tr[tr[u].r].is_homogeneous || tr[u].cnt >= 2;
	}
	void zig(int& x)
	{
		int q = tr[x].l;
		tr[x].l = tr[q].r, tr[q].r = x, x = q;
		pushup(tr[x].r), pushup(x);
	}
	void zag(int& x)
	{
		int q = tr[x].r;
		tr[x].r = tr[q].l, tr[q].l = x, x = q;
		pushup(tr[x].l), pushup(x);
	}
	void build()
	{
		get_node(INF), get_node(-INF);
		root = 1, tr[1].r = 2;
		if (tr[1].val < tr[2].val) zag(root);
	}
	void insert(int& x, int key)
	{
		if (!x) x = get_node(key);
		else if (tr[x].key == key) tr[x].cnt++;
		else if (tr[x].key > key)
		{
			insert(tr[x].l, key);
			if (tr[tr[x].l].val > tr[x].val) zig(x);
		}
		else
		{
			insert(tr[x].r, key);
			if (tr[tr[x].r].val > tr[x].val) zag(x);
		}
		pushup(x);
	}
	void del(int& x, int key)
	{
		if (!x) return;
		if (tr[x].key == key)
		{
			if (tr[x].cnt > 1) tr[x].cnt--;
			else if (tr[x].l || tr[x].r)
			{
				if (!tr[x].r || tr[tr[x].l].val > tr[tr[x].r].val)
				{
					zig(x);
					del(tr[x].r, key);
				}
				else zag(x), del(tr[x].l, key);
			}
			else
			{
				tr[x].cnt--, tr[x].sz--, tr[x].is_homogeneous = false, x = 0;
			}
		}
		else if (tr[x].key > key)
		{
			del(tr[x].l, key);
		}
		else del(tr[x].r, key);
		pushup(x);
	}
};

Treap tp;

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	cin >> n;
	tp.build();
	int cnt = 0;
	while (n--)
	{
		string s;
		cin >> s;
		int k;
		cin >> k;
		if (s == "insert")
		{
			st.insert(k);
			tp.insert(tp.root, k);
			times[k]++;
			cnt++;
		}
		else
		{
			if (st.size() && st.find(k) != st.end())
			{
				if (--times[k] == 0) st.erase(k);
				cnt--;
				tp.del(tp.root, k);
			}
		}
		if (cnt == 0)
		{
			cout << "neither\n";
			continue;
		}
		bool is_homogeneous = tp.tr[tp.root].is_homogeneous;
		bool is_heterogeneous = st.size() > 1;
		if (is_homogeneous && is_heterogeneous) cout << "both\n";
		else if (is_homogeneous && !is_heterogeneous) cout << "homo\n";
		else if (!is_homogeneous && is_heterogeneous) cout << "hetero\n";
		else cout << "neither\n";
	}
	return 0;
}
posted @   HappyBobb  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示