首页 > 其他分享 >[Ynoi2016] 镜中的昆虫 题解

[Ynoi2016] 镜中的昆虫 题解

时间:2024-08-15 20:28:31浏览次数:14  
标签:cl int 题解 cnq iter ++ Ynoi2016 镜中 mp

难度在最近遇到的题里相对较高,在这里写一篇珂学题解。


(以下是学校给的部分分)

\(20\%\):直接暴力枚举。

另外 \(20\%\):假如我们取 \(pre\),对于 \(pre<l\) 的,\(ans++\),明显二维偏序,树状数组或 \(cdq\) 即可,时间复杂度 \(O(n\log n)\)。

另外 \(40\%\):相当于多加一个时间维,三维偏序,\(cdq\) 典中典,时间复杂度 \(O(n\log^2n)\)。

这是正解向的,实际上第二个部分分还可以莫队,第三个部分分还可以分块或带修莫队。


\(100\%\):这里引入珂朵莉树:

模板题 \(CF896C\),也是普遍认为的算法来源。

实际上就是将相同的数合到一个区间,对于区间赋值(珂朵莉树中通常称为推平),直接将这些区间全部并到一块,合成一个区间(珂朵莉树精髓,\(assign\))。时间复杂度在随机数据下,可证明为 \(O(n\log n)\) 级别的,可以自己上网搜。

我们用珂朵莉树维护 \(pre\),就可以保证时间维变成 \(n+m\) 个。

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

//中国珂学院 SNGXYZ 分院 OI 科第三办公室研究员 LYH
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5,M=2e6+5;
int n,m,cnm,cnq,pr[N];
int a[N],lst[N],ans[N],cna;
struct node{
	int x,y,t,v,id;
}q[M];map<int,int>mp;
int cmp1(node x,node y){
	return x.t!=y.t?x.t<y.t:x.id<y.id;
}int cmp2(node x,node y){
	return x.x!=y.x?x.x<y.x:x.id<y.id;
}struct chtholly{
	struct odt{
		int l,r;
		mutable int v;
		bool operator<(const odt &c)const{
			return l<c.l;
		}
	};set<odt>st,cl[N];
	#define iter set<odt>::iterator
	iter ins(int l,int r,int v){
		cl[v].insert({l,r,v});
		return st.insert({l,r,v}).first;
	}void del(int l,int r,int v){
		cl[v].erase({l,r,v});
		st.erase({l,r,v});
	}iter spilt(int x){
		iter it=st.lower_bound({x,0,0});
		if(it!=st.end()&&(*it).l==x) return it;
		it--;int l=(*it).l,r=(*it).r,v=(*it).v;
		del(l,r,v),ins(l,x-1,v);
		return ins(x,r,v);
	}int pre(int x){
		iter it=--st.upper_bound({x,0,0});
		if((*it).l<x) return x-1;
		iter ch=cl[(*it).v].lower_bound({x,0,0});
		return (ch!=cl[(*it).v].begin())*(*(--ch)).r;
	}void assign(int l,int r,int v,int t){
		iter tr=spilt(r+1),tl=spilt(l);
		vector<int>ps;
		for(iter it=tl;it!=tr;it++){
			if(it!=tl) ps.emplace_back((*it).l);
			iter nxt=cl[(*it).v].upper_bound(*it);
			if(nxt!=cl[(*it).v].end()) ps.emplace_back((*nxt).l);
			cl[(*it).v].erase(*it);
		}st.erase(tl,tr);ins(l,r,v);
		ps.emplace_back(l);
		iter nxt=cl[v].upper_bound({l,r,v});
		if(nxt!=cl[v].end()) ps.emplace_back((*nxt).l);
		for(int i=0;i<ps.size();i++){
			q[++cnq]=(node){ps[i],pr[ps[i]],t,-1,0};
			pr[ps[i]]=pre(ps[i]);
			q[++cnq]=(node){ps[i],pr[ps[i]],t,1,0};
		}
	}
}seniorious;
struct BIT{
	int c[N];
	void add(int x,int y){
		for(;x<N;x+=x&-x)
			c[x]+=y;
	}int ans(int x){
		int re=0;
		for(;x;x-=x&-x)
			re+=c[x];
		return re;
	}
}bit;
void cdq(int l,int r){
	if(l==r) return;
	int mid=(l+r)/2;
	cdq(l,mid),cdq(mid+1,r);
	int i=l,j=mid+1;
	while(j<=r){
		while(i<=mid&&q[i].x<=q[j].x){
			if(!q[i].id) bit.add(q[i].y+1,q[i].v);
			i++;
		}if(q[j].id) ans[q[j].id]+=bit.ans(q[j].y+1)*q[j].v;
		j++;
	}for(int k=l;k<i;k++)
		if(!q[k].id) bit.add(q[k].y+1,-q[k].v);
	inplace_merge(q+l,q+mid+1,q+r+1,cmp2);
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(!mp[a[i]])
			mp[a[i]]=++cnm;
		a[i]=mp[a[i]];
		pr[i]=lst[a[i]];
		lst[a[i]]=i;
		q[++cnq]={i,pr[i],0,1,0};
		seniorious.ins(i,i,a[i]);
	}for(int i=1;i<=m;i++){
		int x;cin>>x;
		if(x==1){
			int l,r,v;cin>>l>>r>>v;
			if(!mp[v]) mp[v]=++cnm;
			seniorious.assign(l,r,mp[v],i);
		}else{
			int l,r;cin>>l>>r;
			q[++cnq]={r,l-1,i,1,++cna};
			q[++cnq]={l-1,l-1,i,-1,cna};
		}
	}sort(q+1,q+cnq+1,cmp1);
	cdq(1,cnq);
	for(int i=1;i<=cna;i++)
		cout<<ans[i]<<"\n";
	return 0;
}/*
在太阳西斜的这个世界里,置身天上之森。
等这场战争结束之后,不归之人与望眼欲穿的众人。
人人本着正义之名,长存不灭的过去、逐渐消逝的未来。
我回来了,纵使日薄西山,即便看不到未来。
此时此刻的光辉,盼君勿忘。
————世界上最幸福的女孩
*/

标签:cl,int,题解,cnq,iter,++,Ynoi2016,镜中,mp
From: https://www.cnblogs.com/chang-an-22-lyh/p/18361760/ynoi2016-jingzhongdekuncong-tj

相关文章

  • DELPHI四舍五入问题解决
    转自http://www.delphitop.com/html/jichu/153.html 感谢原作者。 这段时间在用DELPHI做一个财务系统时发现每一行的小计取了两位小数后与用SQL的ROUND查询出来的不一样,在程序中是用FormatFloat('0.00',ItemSum)函数来取值的,再用DXDBGRID网格显视合计,最终与SELECTSUM(ROUND(......
  • 【问题解决】PageOffice打开word文档报错:Office运行时错误,部分系统文件可能丢失或已损
    打开wps,右上角配置和修复工具取消勾选,确定再打开,重新勾选,确定,退出重启电脑,验证。--PS:本人自测成功,有些人的机器安装有MicrosoftOffice,取消之后(不需要重新勾选)就可以了;本人机器只安装了WPS适合这种操作。......
  • P10633 BZOJ2989 数列/BZOJ4170 极光 题解
    题目传送门前置知识CDQ分治|权值树状数组及应用|曼哈顿距离与切比雪夫距离的相互转化解法增加一维为时间戳,那么操作\(1\)等价于单点加。曼哈顿距离直接跑CDQ分治,貌似不太可做,考虑转化为切比雪夫距离。原曼哈顿坐标系中的点\((x_{1},y_{1}),(x_{2},y_{2})\)间的......
  • Ubuntu中编译使用ANTs(医学图像配准)含github无法访问问题解决
    目录第一步、修改hosts文件1.打开https://github.com.ipaddress.com/ 2.打开https://fastly.net.ipaddress.com/github.global.ssl.fastly.net#ipinfo3.打开hosts文件,并在文件末尾添加如下内容 第二步、编译ANTs1)首先安装git、cmake以及c++编译器2)编译3)配置bin目录,......
  • 【题解】CF - 823C : Coin Troubles
    原题传送门题目大意有\(N\)种硬币,两种硬币的面值可能相同。给定\(q\)个限制,第\(i\)个限制由\(b_i\)和\(c_i\)组成,表示第\(b_i\)种硬币的数量严格大于第\(c_i\)种硬币的数量,且每个\(b_i\)与\(c_i\)都是唯一的。问在满足所有限制的情况下,有多少种可能的方案,能组......
  • Django 数据库迁移:makemigrations 和 migrate 命令详解及常见问题解决
    目录1.问题所示2.pythonmanage.pymakemigrations3.pythonmanage.pymigrate4.拓展1.问题所示最初始的状态是遇到这个问题由于刚开始跑pythonweb项目,开源项目附带的Readme,个别命令不太懂,对此详细研究其基本知识最终的解决方案如下:清理迁移文件:删除迁移目......
  • 大模型面试题库精华:100道经典问题解析
    ↓推荐关注↓算法暑期实习机会快结束了,校招大考即将来袭。当前就业环境已不再是那个双向奔赴时代了。求职者在变多,岗位在变少,要求还更高了。最近,我们陆续整理了很多大厂的面试题,帮助网友解惑答疑和职业规划,分享了面试中的那些弯弯绕绕。喜欢本文记得收藏、关注、点赞,更......
  • Ubunto 24.04 下 Docker Desktop 打开无反应问题解决和原因
    背景系统环境:Ubuntu24.04LTSDocker版本:Dockerversion26.1.4问题表象:打开DockerDesktop之后,无任何反应,使用命令行直接运行DockerDesktop,提示:runningundersystemd解决方案命令行执行如下指令$sudosysctl-wkernel.apparmor_restrict_unprivileged_userns=0$......
  • CF1530D Secret Santa 题解
    ProblemSolution每个人初始不会给自己送礼物。如果每人要送礼的人都不一样,答案即为\(n\)。如果有两个或以上的人要送给同一个人礼物,假设有\(x\)个人要给同一个人送礼物,那么必有\(x-1\)个人要更改送礼的人,并将礼物送个\(x-1\)个没有礼物收的人。然而这样送礼物可能会导......