首页 > 其他分享 >[Tkey] 黑兔子,白兔子

[Tkey] 黑兔子,白兔子

时间:2024-07-24 21:18:29浏览次数:13  
标签:lazy int dsu 兔子 id tag release Tkey

CL-21

一般拿到这个题第一眼都应该能看出并查集,subtask1 是给并查集暴力修改的.

后面 subtask2 没有联通操作,是给纯线段树的,也算是启发正解了

再往下可以考虑操作 \(1\) 采用线段树区间修改,操作 \(2\) 采用并查集维护的思路. 按这个思路去想,那么操作 \(2\) 肯定不能进行修改,因为我们无法快速知道哪些元素在本并查集里,就算知道,暴力去修改也容易被卡到 \(O(n)\). 既然这样的话,考虑到同一个并查集里的元素都相等,因此我们就考虑用并查集里的代表元素去表示这个并查集最终的颜色,这样我们在操作二中仅需修改一个点即可.

因为我们懒惰地进行了操作二,现在的问题就是如何去判断一个并查集里的最终颜色到底是哪个,根据颜色会进行覆盖的思想,我们给每个颜色再开一个时间戳,表示该颜色被修改的顺序,这样我们仅需要在最后遍历一遍线段树叶节点,找出哪个颜色的时间戳最大,就把它作为该并查集的颜色.

有一些需要注意的细节,请注意你最后扫的那一遍是否为不完全更新. 一开始的 STD 就是因为在扫的时候不完全更新了,因此最后挂了八十多分. 我对此的解决办法是扫两遍,也许大家还有更好的策略.

还有一些不必要的小优化,其实因为这个线段是只在最后询问一次,所以在更新操作的时候完全没必要 pushdown(),直接覆盖就行了.

#include<bits/stdc++.h>
using namespace std;
const int N=1000001;
int n,m,k;
int root[N],tagroot[N],ans[N];
namespace dsu{
	int p[N];
	void clear(){
		for(int i=1;i<=n;++i){
			p[i]=i;
			tagroot[i]=1;
			root[i]=1;
		}
	}
	int find(int id){
		if(p[id]==id){
			return id;
		}
		p[id]=find(p[id]);
		return p[id];
	}
}
namespace stree{
	#define tol (id*2)
	#define tor (id*2+1)
	#define mid(l,r) mid=((l)+(r))/2
	struct tree{
		int tag,lazy;
		int l,r;
	}t[4*N];
	void build(int id,int l,int r){
		t[id].l=l;t[id].r=r;
		if(l==r) return;
		int mid(l,r);
		build(tol,l,mid);
		build(tor,mid+1,r);
	}
	void update(int id,int l,int r,int k,int tt){
		if(t[id].l>t[id].r or t[id].r<l or t[id].l>r) return;
		if(t[id].l>=l and t[id].r<=r){
			t[id].lazy=k;
			t[id].tag=tt;
			return;
		}
		int mid(t[id].l,t[id].r);
		update(tol,l,r,k,tt);
		update(tor,l,r,k,tt);
	}
	void pushdown(int id){
		if(t[id].tag>t[tol].tag){
			t[tol].lazy=t[id].lazy;
			t[tol].tag=t[id].tag;
		}
		if(t[id].tag>t[tor].tag){
			t[tor].lazy=t[id].lazy;
			t[tor].tag=t[id].tag;
		}
	}
	void release(int id){
		if(t[id].l==t[id].r){
			int x=dsu::find(t[id].l);
			if(tagroot[x]>t[id].tag){
				ans[t[id].l]=root[x];
			}
			else{
				ans[t[id].l]=t[id].lazy;
				tagroot[x]=t[id].tag;
				root[x]=t[id].lazy;
			}
			return;
		}
		pushdown(id);
		release(tol);
		release(tor);
	}
}
int main(){
	cin>>n>>m>>k;
	dsu::clear();
	int op,l,r,x;
	stree::build(1,1,n);
	for(int i=1;i<=m;++i){
		cin>>op>>l>>r>>x;
		if(op==1){
			stree::update(1,l,r,x,i+1);
		}
		else{
			int a=dsu::find(l),b=dsu::find(r);
			root[b]=x;
			tagroot[b]=i+1;
			if(a!=b){
				dsu::p[a]=b;
			}
		}
	}
	stree::release(1);
	stree::release(1);
	for(int i=1;i<=n;++i){
		cout<<ans[i]<<" ";
	}
	cout<<endl;
} 

标签:lazy,int,dsu,兔子,id,tag,release,Tkey
From: https://www.cnblogs.com/HaneDaCafe/p/18321746

相关文章

  • ControlMyMonitor、MultiMonitorTool、autohotkey 设置笔记本和台式机切换屏幕
    一、背景1.1台笔记本、1台台式机共用一个显示器。2.显示器1个vga输入、1个hdmi输入3.笔记本通过hdmi转vga连到显示器,台式机通过HDMI连到显示器二、需求通过键盘切换显示器输入。三、软件介绍ControlMyMonitor:控制显示器输入方式(选择vga、hdmi)MultiMonitorTool:控制电脑在哪......
  • 华为OD机考题(HJ37 统计每个月兔子的总数)
    前言经过前期的数据结构和算法学习,开始以OD机考题作为练习题,继续加强下熟练程度。描述有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。一月的时候有一只兔子,假......
  • AutoHotKey自动热键(五)添加WINDOWS秘笈指令-输入瞬间启动功能
    在AUTOHOTKEY的使用中,不仅仅可以监听组合热键,还可以监听正常文本击键录入,这是另一种监听方式,比如依次击键jsq之后直接弹出<计算器>工具,或者依次击键sj之后直接输出135****5564的手机号码,等等,这就是autohotkey的录入击键监听,以双冒号为开头::因这种录入监听像极了......
  • P4688 Ynoi2016 掉进兔子洞
    P4688Ynoi2016掉进兔子洞经典莫队加bitset。思路不难发现最终答案就是:\[(r_1-l_1+1)+(r_2-l_2+1)+(r_3-l_3+1)-3\timessize\]其中\(size\)表示3个区间内出现了多少个公共元素。看到这么多区间,不妨有把区间拆下来搞莫队的想法。先不考虑询问个数的限制,我们考虑使用......
  • 浅谈一下Mybatis当中插入主键返回的两个属性(useGeneratedKeys,selectKey)
    useGeneratedKeys和selectKey的区别今天遇见两个Mybatis当中很有像似点的属性,仔细研究了会.发现还是有带你不同.useGenerateKeys其值为true和false,表明是否将插入生成的主键返回到参数当中.useGeneratedKey属性会自动根据驱动生成对应SQL语句useGeneratedKey只支持“......
  • [Tkey] 与非
    解法原理1首先我们需要明白\(\operatorname{nand}\)的运算:\[\operatorname{not}(a\operatorname{nand}b)=a\operatorname{and}b\tag{1}\]这个很好理解,因为\(\operatorname{nand}\)就是这么定义的(从中文名字可以看出来)。\[(\operatorname{not}a)\operatorname{nand}(\opera......
  • 在 C# 中对比KeyValuePair<TKey, TValue> 和 IDictionary<TKey, TValue>
    C#中的KeyValuePair<TKey,TValue>和IDictionary<TKey,TValue>具有独特的用途并表现出不同的特征。KeyValuePair<TKey,TValue>的功能KeyValuePair<TKey,TValue>是存储单个键值对的数据结构。它属于System.Collections.Generic命名空间。用法它用于表示单个......
  • [Tkey] A decorative fence
    还是看看简单而富有美感的爆搜吧#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definetestsintcases;cin>>cases;while(cases--)intn,l;vector<int>e;boolvis[21];intcnt=0;voiddfs(intp){ if(cnt==l)return; if(p>n){ cnt++......
  • [Tkey] 生日礼物
    题意简述彩珠有\(n\)个\(k\)种,每个珠子都有一个坐标\(p_{i}\),求最小的区间长度,使得这个区间包含全部的\(k\)种彩珠.分析发现我们可以维护每一种颜色的最近出现坐标.因为是最近的出现坐标,所以离现在的距离(即答案)一定是更优的,那么我们用这个值来更新答案一定就是最优的.......
  • [Tkey] CodeForces 1267G Game Relics
    太神了这题,膜拜出题人orz。思考一首先是大家都提到的一点,先抽卡再买。这里来做个数学分析。假设我们还剩\(k\)种没有买,其实我们是有式子来算出它的花费期望的。WIKI上提到,假设一个事件的概率为\(p\),则遇到它的期望为\(\frac{1}{p}\),因此,对于这个题,抽到一个新物品的概率显......