首页 > 其他分享 >[HNOI2009] 梦幻布丁

[HNOI2009] 梦幻布丁

时间:2024-09-29 19:12:11浏览次数:8  
标签:cnt val rs int 布丁 梦幻 ls HNOI2009 id

[HNOI2009] 梦幻布丁

题意

给出一个序列 \(a\),有 \(q\) 次操作,每次修改把序列中一种数全部改为另一种数。

每次询问,查询序列 \(a\) 的颜色段个数。

思路

颜色段只有同一种颜色才有贡献,我们考虑每种颜色开一棵平衡树维护。

每种颜色维护其在原序列中的下标,下标连续的一段区间就是一个颜色段。

每次改变颜色,相当于把两种颜色合并在一起,使用启发式合并即可。

时间复杂度:\(O(n\log^2n)\)。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 3e6 + 5;
template <typename T> 
void read(T& x) {
	x = 0; T f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-') f = -f;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	x = x * f;
}
void write(int x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
struct treap {
	struct node {
		int ls, rs, val;
		int cnt, l, r;	
		int key, siz;
	} t[N];
	int tot, root[N];
	int top, rub[N]; 
	int new_node(int v) {
		int id;
		if (top) id = rub[top --];
		else id = ++ tot;
		t[id].ls = t[id].rs = 0;
		t[id].val = v, t[id].cnt = 1;
		t[id].l = t[id].r = v;
		t[id].key = rand();
		t[id].siz = 1; 
		return id;
	}
	void push_up(int p) {
		t[p].siz = t[t[p].ls].siz + t[t[p].rs].siz + 1;
		if (t[p].ls && t[p].rs) {
			t[p].cnt = t[t[p].ls].cnt + t[t[p].rs].cnt + 1;
			t[p].l = t[t[p].ls].l, t[p].r = t[t[p].rs].r;
			if (t[t[p].ls].r == t[p].val - 1) 
				t[p].cnt --; 
			if (t[p].val + 1 == t[t[p].rs].l)
				t[p].cnt --;
		} else if (t[p].ls) {
			t[p].cnt = t[t[p].ls].cnt + 1;
			t[p].l = t[t[p].ls].l, t[p].r = t[p].val;
			if (t[t[p].ls].r == t[p].val - 1) 
				t[p].cnt --; 
		} else if (t[p].rs) {
			t[p].cnt = t[t[p].rs].cnt + 1;
			t[p].l = t[p].val, t[p].r = t[t[p].rs].r;
			if (t[p].val + 1 == t[t[p].rs].l)
				t[p].cnt --;
		} else {
			t[p].cnt = 1;
			t[p].l = t[p].r = t[p].val;			
		}
	}
	void split(int p, int k, int &x, int &y) {
		if (!p) {x = 0, y = 0; return ;}
		if (t[p].val <= k) {
			x = p;
			split(t[p].rs, k, t[p].rs, y);
		} else {
			y = p;
			split(t[p].ls, k, x, t[p].ls);
		}
		push_up(p);
	}
	int merge(int x, int y) {
		if (!x || !y) return x + y;
		if (t[x].key > t[y].key) {
			t[x].rs = merge(t[x].rs, y);
			push_up(x);
			return x;	
		} else {
			t[y].ls = merge(x, t[y].ls);
			push_up(y);
			return y;
		}
	}
	void insert(int &id, int val) {
		int x, y;
		split(id, val, x, y);
		id = merge(merge(x, new_node(val)), y);
	}
	int query(int id) {return t[id].cnt;}
	void bmerge(int id, int &id2) {
		if (!id) return ;
		if (t[id].ls) bmerge(t[id].ls, id2);
		if (t[id].rs) bmerge(t[id].rs, id2);
		insert(id2, t[id].val);
		rub[++ top] = id;
	}
} T;
int n, m, ans, a[N];
void modify(int x, int y) {
	if (x == y) return ;
	ans -= T.query(T.root[x]);
	ans -= T.query(T.root[y]);
	int id1, id2; // id1 -> id2 
	if (T.t[x].siz < T.t[y].siz) 
		id1 = x, id2 = y;
	else id1 = y, id2 = x; 
	T.bmerge(T.root[id1], T.root[id2]);
	T.root[y] = T.root[id2];
	T.root[x] = 0;
	ans += T.query(T.root[y]);
}
int main() {
	srand(time(0));
	read(n); read(m);
	for (int i = 1; i <= n; i ++) {
		read(a[i]);
		T.insert(T.root[a[i]], i);
	}
	for (int i = 1; i <= 1e6; i ++) 
		ans += T.query(T.root[i]);
	while (m --) {
		int op, x, y;
		read(op);
		if (op == 1) {
			read(x); read(y);
			modify(x, y);
		} else {
			write(ans); putchar('\n');
		}
	}
	return 0;
}

标签:cnt,val,rs,int,布丁,梦幻,ls,HNOI2009,id
From: https://www.cnblogs.com/maniubi/p/18440609

相关文章

  • 梦幻西游端游多开搬砖攻略,GameViewer远程助力高效查看操控搬砖进度
    想要电脑装进手机,手机实现多开梦幻西游搬砖,不占内存、不发烫就选网易GameViewer远程。作为梦幻西游的老玩家,拥有多个账号,都想要搬砖,这款软件就能让你的手机或是平板免费远控电脑,多开玩梦幻西游端游,而且不占内存,不发烫,高效查看操控搬砖进度。使用网易GameViewer远程进行梦......
  • 手机如何五开玩梦幻西游端游?用GameViewer远程手机免费畅玩梦幻西游
    用手机就能免费玩梦幻西游端游,还可以随时查看挂机进度!想要实现这一点,就用网易GameViewer远程,而且不光手机可以玩梦幻西游端游,平板也能免费玩,并为你实现五开玩梦幻西游端游。那么,通过GameViewer远程你都能体验到什么呢?你能体验到4K蓝光144帧的高画质和百分百还原梦幻......
  • 天后回归!联诚发LED巨幕助力张韶涵打造梦幻舞台,唱响哈尔滨!
    张韶涵第101场演唱会,她的音乐梦想再次起航。时隔六年,她重返魅力四射的哈尔滨,在这里,她的音乐再次谱写了华丽的篇章。在这场哈尔滨的演出中,张韶涵带来了全新的舞美设计、音响系统、服装造型以及妆造,标志着她音乐之旅的一个崭新起点。在哈尔滨演唱会上,张韶涵用她那经过多年沉淀的舞台......
  • 【AI 生图赢奖】用函数计算绘出「少年江湖」,与热播网剧梦幻联动
    在这个数字化时代,人工智能不再只是科幻小说中的幻想,创意与技术的界限正在被重新定义。摩拳擦掌研究AI的你,是否想用自己的新技术和创造力一试身手呢?阿里云联合优酷推出【少年白马醉春风·AI江湖创作大赛】,无论您是开发者、设计师、还是AI绘画爱好者,都可以使用阿里云函数计......
  • 超写实魅力:26岁时尚女孩的胶片质感肖像,长发下的精致面容与梦幻水泡环绕,性感身姿在戏剧
    极致真实与品质的呈现:26岁时尚女孩的超写实肖像,长发飘逸,精致面容,环绕着超现实的漂浮水泡,水花细节与戏剧性光影交错,复古胶片风格下的瞬间眼神,展现美丽与性感的全身形象。正向提示词(ultrarealistic,bestquality),photorealisticportraitof26yohubggirl,Sheisstyli......
  • 开始梦幻之旅--C++
    生活中有许多人人在忙忙碌碌,其中的许多人s都不会想到他们会被代替那个代替别人的东西就是人工智能人工智能是什么,他由什么来做成的呢人工智能是什么早在二战时期,图灵就已经开始了图灵测试,具体如下:一名测试者写下自己的问题,随后将问题以纯文本的形式(如计算机屏幕和键盘)发送......
  • 梦幻布丁
    假设现在有\(n\)个元素,每个元素最开始单独成为一个集合现在有一种合并操作,可以合并两个集合,假设将集合\(A\)合并到集合\(B\),那么时间复杂度为\(O(|A|p)\),其中\(O(p)\)表示合并一个元素的操作的复杂度,也就是说我们的操作每次是合并一个元素和一个集合,所以我们将\(A\)合并到\(B\)里......
  • P3200 [HNOI2009] 有趣的数列
    哇,太恶心了思路首先我们将题意简化,简化后为对于任意一个偶数位所填数必然大于等于自己的下标,那么考虑填数,如果填的偶数比奇数多,那么此时要么填尽偶数后失败,或者下一个位置填奇数就炸,比如偶数刚好多一个,那么必然有一个偶数放在了奇数位,那么本来下一个要填的偶数往前移了一个,导致......
  • 探索梦幻之旅:一场说走就走的旅游攻略!
    在这个快节奏的时代,偶尔放慢脚步,踏上一场说走就走的旅行,成为了许多人心中最温柔的向往。无论是追寻历史的足迹,还是沉浸于自然的怀抱,每一次旅行都是一次心灵的洗礼。今天,就让我们一起规划一场梦幻般的旅程,探索那些隐藏在地图角落的绝美风景与文化瑰宝。一、前期准备:细致规划,轻......
  • 【AI生图赢奖】用函数计算绘出「少年江湖」,与热播网剧梦幻联动
    在这个数字化时代,人工智能不再只是科幻小说中的幻想,创意与技术的界限正在被重新定义。摩拳擦掌研究AI的你,是否想用自己的新技术和创造力一试身手呢?阿里云联合优酷推出【少年白马醉春风·AI江湖创作大赛】,无论您是开发者、设计师、还是AI绘画爱好者,都可以使用阿里云函数计算......