[Ynoi2016] 镜中的昆虫 题解
难度在最近遇到的题里相对较高,在这里写一篇珂学题解。
(以下是学校给的部分分)
\(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;
}/*
在太阳西斜的这个世界里,置身天上之森。
等这场战争结束之后,不归之人与望眼欲穿的众人。
人人本着正义之名,长存不灭的过去、逐渐消逝的未来。
我回来了,纵使日薄西山,即便看不到未来。
此时此刻的光辉,盼君勿忘。
————世界上最幸福的女孩
*/
[Ynoi2016] 镜中的昆虫 题解的更多相关文章
- [Ynoi2016]镜中的昆虫
题目大意: 给定一个序列,有2个操作: 1. 区间覆盖.2. 区间数颜色. 解题思路: 珂朵莉树+树套树. 看到区间覆盖当然想到珂朵莉树然而这是Ynoi 所以我们得优化掉珂朵莉树那个暴力过程. 考虑对 ...
- bzoj4941: [Ynoi2016]镜子里的昆虫
维护每个位置x的上一个相等的位置pv[x],可以把询问表示成l<=x<=r,pv[x]<l的形式,对一次修改,均摊改变O(1)个pv的取值,因此可以用平衡树预处理出pv的变化,用cd ...
- 洛谷P1554 梦中的统计 题解
题目传送门 这道题暴力又让我过了...数据真的很水(luogu) 暴力枚举n~m的每个数,再统计一次,交付评测...AC #include<bits/stdc++.h> using nam ...
- 2021record
2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...
- Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)
Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...
- ZJOI2019Round#1
考的这么差二试基本不用去了 不想说什么了.就把这几天听课乱记的东西丢上来吧 这里是二试乱听课笔记ZJOI2019Round#2 ZJOI Round#1 Day1 M.<具体数学>选讲 罗 ...
- 51nod 1277 字符串中的最大值
题目链接 51nod 1277 字符串中的最大值 题解 对于单串,考虑多串的fail树,发现next数组的关系形成树形结构 建出next树,对于每一个前缀,他出现的次数就是他子树的大小 代码 #inc ...
- LeetCode题解汇总(包括剑指Offer和程序员面试金典,持续更新)
LeetCode题解汇总(持续更新,并将逐步迁移到本博客列表中) LeetCode题解分类汇总(包括剑指Offer和程序员面试金典) 剑指Offer 序号 题目 难度 03 数组中重复的数字 简单 0 ...
- 病毒侵袭持续中 HDU - 3065 AC自动机
小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒 ...
- 2020级cpp上机考试题解#B卷
A卷的第七题我只会一个个排除的方法 意思就是暂时没有好办法所以A卷不搞了 1:递归函数求数列 题意: 有一个递归函数int f(int m),计算结果代表了数列的第m项.当m等于1时,函数结果返回1: ...
随机推荐
- Coqui TTS合成语音
工具介绍 Coqui TTS是一个用于语音转文本的高性能深度学习模型库.提供1100种语言的预训练模型,提供训练新模型和微调已有模型的工具,提供数据集分析工具.XTTS-v2版本支持16种语言: En ...
- 实现不可逆加密文件:探索 GodoOS 的安全机制
在当今数字化时代,数据安全成为了企业和个人关注的重点.为了保护敏感信息不被未授权访问,各种加密技术应运而生.本文将探讨 GodoOS 项目中实现的一种不可逆加密文件的方法,重点介绍其背后的原理和技术细 ...
- 【分块】LibreOJ 6280 数列分块入门4
题目 https://loj.ac/p/6280 题解 将 \(n\) 个元素的数组 \(a\) 按块长 \(\sqrt{n}\) 进行分块处理.为每个块设置两个懒添加标记 \(add[i], sum ...
- Qt开源作品6-通用视频控件
一.前言 在之前做的视频监控系统中,根据不同的用户需要,做了好多种视频监控内核,有ffmpeg内核的,有vlc内核的,有mpv内核的,还有海康sdk内核的,为了做成通用的功能,不同内核很方便的切换,比 ...
- WIN10删除文件时提示“找不到该项目,该项目不在......中,请确认该项目的位置,然后重试”的解决办法
问题描述: 最近有部分WIN10用户在删除文件时提示"找不到该项目,该项目不在......中,请确认该项目的位置,然后重试". 解决办法: 1.首先新建一个TXT文档(为了方便使用 ...
- win7语言栏不见了,只显示搜狗输入法,不显示中文(简体)-美式键盘
参考百度经验: win7右下角输入法图标不见了[终极方法]
- 在C++中实现委托事件的方法
参考链接: 1.在C++中模拟委托事件的方法(一) 2.利用C++的模板模拟.net的代理语法 源码学习: 1.https://pan.baidu.com/s/15vbryvzDnvmJ6FMku6_ ...
- 解密Prompt45. 再探LLM Scalable Oversight -辩论、博弈哪家强
之前我们已经介绍过几个针对Scalable Oversight的解法,也就是当模型能力在部分领域超越人类标注者后,我们该如何继续为模型提供监督信号,包括 持续提升Verifier的能力,辅助人类提供监 ...
- IM消息ID技术专题(七):网易严选分布式ID的技术选型、优化、落地实践
1.引言 在<IM消息ID技术专题>系列文章的前几篇中,我们已经深切体会到消息ID在分布式IM聊天系统中的重要性以及技术实现难度,各种消息ID生成算法及实现虽然各有优势,但受制于具体的应用 ...
- Python 代码实现生命之轮Wheel of life
最近看一个生命之轮的视频,让我们珍惜时间,因为一生是有限的.使用Python创建生命倒计时图表,珍惜时间,活在当下. 生命之轮(Wheel of life),这一概念最初由 Success Motiv ...