Solution -「YunoOI 2016」镜中的昆虫
Description
Link.
- 区间推平;
- 区间数颜色。
Solution
考虑无修的情况,我们是采用维护每个数的 \(pre\) 来做的。具体一点就是对于每一个 \(a_{i}\) 维护 \(pre_{i}=\max\{j\in[1,i),s.t.a_{j}=a_{i}\}\)。然后数区间内 \(pre\) 严格小于左端点的元素个数。
区间推平不好做,考虑削弱这一层修改,考虑单点修改怎么做。
修改一个 \(a_{i}=x\),则受影响的下标有:
- \(j,s.t.pre_{j}=i\);
- \(i\);
- \(\min\{j\in(i,n],s.t.a_{j}=x\}\)。
这个东西套个 std::map 能直接维护。
对于区间修改,有这样的结论:
对于所有修改,\(pre\) 变化次数为 \(\mathcal{O}(n+m)\)。
做不来区间推平翻题解翻来的,至于证明不太会,摊还分析证复杂度没用过。
反正综上就能做了嘛,不知道为什么那么多人都喜欢写树套树,反正我是 CDQ。
//in the autumn sky
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
struct oper
{
int opt,opl,opr,opx;
oper(int A=0,int B=0,int C=0,int D=0){opt=A,opl=B,opr=C,opx=D;}
};
struct ST_modify
{
int ID,pos,pr,val;
ST_modify(int A=0,int B=0,int C=0,int D=0){ID=A,pos=B,pr=C,val=D;}
bool operator<(const ST_modify &ano)const{return pr<ano.pr;}
};
struct ST_query
{
int ID,l,r;
ST_query(int A=0,int B=0,int C=0){ID=A,l=B,r=C;}
bool operator<(const ST_query &ano)const{return l<ano.l;}
};
vector<int> pri;
vector<ST_modify> mod;
vector<ST_query> que;
int pre[100010],n,m,tr[100010],curInd,ans[100010];
map<int,int> mapo[200010];
map<int,pair<int,int> > exmapo; // for ODT
#define lowbit(x) ((x)&(-(x)))
void ins(int pos,int delta)
{
++pos;
while(pos<=n)
{
tr[pos-1]+=delta;
pos+=lowbit(pos);
}
}
int find(int pos)
{
int res=0;
while(pos)
{
res+=tr[pos-1];
pos^=lowbit(pos);
}
return res;
}
void ODT_split(int pos)
{
auto iter=exmapo.lower_bound(pos);
int stan=n;
if(iter!=exmapo.end()) stan=iter->fs;
if(stan^pos)
{
--iter;
exmapo.emplace(pos,iter->sc);
auto exiter=mapo[iter->sc.sc].emplace(pos,iter->sc.fs).fs;
iter->sc.fs=pos;
prev(exiter)->sc=pos;
}
}
void pushOp(int pos,int after,int ID)
{
mod.emplace_back(ST_modify(ID,pos,pre[pos],-1));
pre[pos]=after;
mod.emplace_back(ST_modify(ID,pos,after,1));
}
void rawGrass(int onel,int oner,int anol,int anor,int parl,int parr)
{
if(onel==oner || anol==anor)
{
sort(mod.begin()+onel,mod.begin()+oner);
sort(que.begin()+anol,que.begin()+anor);
}
else
{
int mid=(parl+parr)>>1,exmid1=onel,exmid2=anol;
while(exmid1<oner && mod[exmid1].ID<mid) ++exmid1;
while(exmid2<anor && que[exmid2].ID<mid) ++exmid2;
rawGrass(onel,exmid1,anol,exmid2,parl,mid);
rawGrass(exmid1,oner,exmid2,anor,mid,parr);
int ex=onel;
for(int i=exmid2;i<anor;++i)
{
while(ex<exmid1 && mod[ex].pr<que[i].l) ins(mod[ex].pos,mod[ex].val),++ex;
ans[que[i].ID]+=find(que[i].r)-find(que[i].l);
}
for(int i=onel;i<ex;++i) ins(mod[i].pos,-mod[i].val);
inplace_merge(mod.begin()+onel,mod.begin()+exmid1,mod.begin()+oner);
inplace_merge(que.begin()+anol,que.begin()+exmid2,que.begin()+anor);
}
}
int main()
{
scanf("%d %d",&n,&m);
vector<int> a(n);
vector<oper> b(m);
for(int &i:a) scanf("%d",&i),pri.emplace_back(i);
for(oper &i:b)
{
scanf("%d %d %d",&i.opt,&i.opl,&i.opr);
if(i.opt==1) scanf("%d",&i.opx),pri.emplace_back(i.opx);
--i.opl;
}
sort(pri.begin(),pri.end());
pri.erase(unique(pri.begin(),pri.end()),pri.end());
for(int &i:a) i=lower_bound(pri.begin(),pri.end(),i)-pri.begin();
for(oper &i:b)
{
if(i.opt==1) i.opx=lower_bound(pri.begin(),pri.end(),i.opx)-pri.begin();
}
curInd=0;
for(int i:a)
{
if(mapo[i].size()!=int(0)) pre[curInd]=prev(mapo[i].end())->fs;
else pre[curInd]=-1;
mod.emplace_back(ST_modify(-1,curInd,pre[curInd],1));
mapo[i].emplace(curInd,curInd+1);
exmapo.emplace(curInd,make_pair(curInd+1,i));
++curInd;
}
curInd=0;
for(oper i:b)
{
int ty=i.opt,l=i.opl,r=i.opr,x=i.opx;
if(ty==1)
{
ODT_split(l),ODT_split(r);
auto iter=mapo[x].lower_bound(l);
auto ptr=exmapo.lower_bound(l);
int rpe=(iter!=mapo[x].begin())?((iter=prev(iter))->sc-1):(-1); // for Suf
while(ptr!=exmapo.end())
{
if(ptr->fs==r) break;
pushOp(ptr->fs,rpe,curInd);
int tmp=ptr->sc.sc;
auto exiter=mapo[tmp].erase(mapo[tmp].find(ptr->fs));
if(exiter!=mapo[tmp].end())
{
if(exiter==mapo[tmp].begin()) pushOp(exiter->fs,-1,curInd);
else pushOp(exiter->fs,prev(exiter)->sc-1,curInd);
}
rpe=ptr->sc.fs-1;
ptr=exmapo.erase(ptr);
}
iter=mapo[x].lower_bound(r);
if(iter!=mapo[x].end()) pushOp(iter->fs,r-1,curInd);
exmapo.emplace(l,make_pair(r,x));
mapo[x].emplace(l,r);
}
else que.emplace_back(ST_query(curInd,l,r));
++curInd;
}
rawGrass(0,int(mod.size()),0,int(que.size()),-1,m);
curInd=0;
for(oper i:b)
{
if(i.opt==2) printf("%d\n",ans[curInd]);
++curInd;
}
return 0;
}
Solution -「YunoOI 2016」镜中的昆虫的更多相关文章
- Solution -「SDOI 2016」「洛谷 P4076」墙上的句子
\(\mathcal{Description}\) Link. (概括得说不清话了还是去看原题吧 qwq. \(\mathcal{Solution}\) 首先剔除回文串--它们一定对答案产 ...
- Solution -「ZJOI 2016」「洛谷 P3352」线段树
\(\mathcal{Descrtiption}\) 给定 \(\{a_n\}\),现进行 \(m\) 次操作,每次操作随机一个区间 \([l,r]\),令其中元素全部变为区间最大值.对于每个 \ ...
- Solution -「CERC 2016」「洛谷 P3684」机棚障碍
\(\mathcal{Description}\) Link. 给一个 \(n\times n\) 的网格图,每个点是空格或障碍.\(q\) 次询问,每次给定两个坐标 \((r_1,c_1), ...
- Solution -「NOI 2016」「洛谷 P1587」循环之美
\(\mathcal{Description}\) Link. 给定 \(n,m,k\),求 \(x\in [1,n]\cap\mathbb N,y\in [1,m]\cap \mathbb ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- [转帖]「日常小记」linux中强大且常用命令:find、grep
「日常小记」linux中强大且常用命令:find.grep https://zhuanlan.zhihu.com/p/74379265 在linux下面工作,有些命令能够大大提高效率.本文就向大家介绍 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
随机推荐
- 快速上手kettle(三)壶中可以放些啥?
目录 序言 一 .kettle这壶能装些啥 二.Access输入 2.1 准备Acess数据库和表 2.2 新建一个转换并设置 2.3 启动转换预览数据 三.CSV文件输入 3.1 准备csv文件,并 ...
- Java 新的生态,Solon v2.3.2 发布
Solon 是什么框架? 一个,Java 新的生态型应用开发框架.它从零开始构建,有自己的标准规范与开放生态(全球第二级别的生态).与其他框架相比,它解决了两个重要的痛点:启动慢,费资源. 解决痛点? ...
- 【python基础】复杂数据类型-字典(遍历)
一个字典可能只包含几个键值对,也可能包含数百万个键值对,所以Python支持字典遍历.字典可用于以各种方式存储信息,因此有多种遍历字典的方式:可遍历字典的所有键值对.键或值. 1.遍历所有的键值对 其 ...
- SpringBoot项目启动 报错:Error executing Maven. end tag name </settings> must match start tag name
SpringBoot项目启动 报错:Error executing Maven. end tag name must match start tag name from line xxx 第一次创建s ...
- 【python基础】类-模块
随着不断给类添加功能,文件可能变得很长,即便妥善地使用了继承亦是如此,为遵循Python的总体理念,应让文件尽可能简洁.为在这方面提供帮助,Python允许将类存储在模块中,然后在主程序中导入所需的模 ...
- Mininet教程
mininet的安装 1.前言 1.本次安装环境为ubuntu20.04. 2.mininet 为 github上的最新版,我已经修改镜像地址并克隆到了gitee,只需要从我的gitee仓库克隆即可. ...
- 揭开 RocketMQ 事务消息的神秘面纱
事务消息是 RocketMQ 的高级特性之一,相信很多同学都对于其实现机制很好奇. 这篇文章,笔者会从应用场景.功能原理.实战例子.实现细节四个模块慢慢为你揭开事务消息的神秘面纱. 1 应用场景 以电 ...
- ISP图像处理——紫边Purple Fringing检测
之前写过文章记紫边的形成原因,以下小结改善方法 图像紫边存在数码相机.监控摄像头等数字成像图像,使用设备在逆光.大光圈条件下拍摄图像的高反差区域容易出现紫边,解决图像自编问题有助设备得到完美图像. 紫 ...
- Mediabox:年度最佳音视频开发工具
"2023稀土开发者大会"落下帷幕,由稀土掘金社区评选的的掘金技术引力榜重磅出炉,共有22个优秀实践案例上榜,涵盖对技术行业发展有特别贡献的人物.开发工具.开源项目.技术团队和技术 ...
- .net 6 winform启动器:调用CMD命令行执行dotnet命令启动.net core程序并将控制台输出日志输出到winform textbox实现实时日志显示
背景 历史遗留问题,生产车间运行的一个.net core signalr程序使用命令行程序启动,经常由于生产人员误操作将光标停留在控制台上导致程序假死,丢失部分测试数据,车间随便找了一台win10系统 ...