[Ynoi2018]未来日记
"望月悲叹的最初分块" (妈呀这名字好中二啊(谁叫我要用日本轻小说中的东西命名真是作死))
这里就直接挂csy的题解了,和我的不太一样,但是大概思路还是差不多的,我的做法是和“五彩斑斓的世界”有点类似的维护方法
先考虑如何求区间第k小值。对序列和权值都进行分块,设bi,j表示前j 块中权值在i 块内的数字个数,ci,j 表示前j 块中数字i 的出现次数。那么对于一个询问[l,r] ,首先将零碎部分的贡献加入到临时数组tb 和tc 中,然后枚举答案位于哪一块,确定位于哪一块之后再暴力枚举答案即可在O(√n) 的时间内求出区间第k小值。
接着考虑如何实现区间[l,r]内x 变成y 的功能。显然对于零碎的两块,可以直接暴力重构整块。对于中间的每个整块,如果某一块不含x ,那么无视这一块;否则如果这一块不含y ,那么只需要将x 映射成y ;否则这一块既有x 又有y ,这意味着x 与y 之间发生了合并,不妨直接暴力重构整块。因为有c 数组,我们可以在O(1) 的时间内知道某一块是否有某个数。
考虑什么情况下会发生重构,也就是一个块内发生了一次合并的时候。一开始长度为nn 的序列会提供O(n) 次合并的机会,而每次修改会对零碎的两块各提供一次机会,故总合并次数不超过O(n+m) ,因此当发生合并时直接重构并不会影响复杂度。
那么现在每块中的转换情况只可能是一条条互不相交的链,只需要记录每个初值转换后是什么,以及每个现值对应哪个初值即可。遇到查询的时候,我们需要知道零碎部分每个位置的值,不妨直接重构那两块,然后遍历一遍原数组a即可得到每个位置的值。
在修改的时候,还需要同步维护b 和c 数组,因为只涉及两个权值,因此暴力修改j 这一维也是可以承受的。
总时间复杂度O((n+m)√n) ,空间复杂度O(n√n)
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+,BLO=;
int n,m,a[N],p,vec[N],v2[BLO];
int bl[N],L[BLO],R[BLO];
int s1[BLO][BLO],s2[BLO][N],id[BLO][N],rid[BLO][BLO],pos[N];
int sta[],ttop=,lp=;
char pr[];
template <typename T> inline void read(T &x) {
x=;register char flag,c=getchar();while(c<''||c>'') flag=c,c=getchar();
while(c>=''&&c<='') x=x*+(c^),c=getchar(); if(flag=='-') x=-x;
}
template <typename T> inline void print(T x) {
ttop=; do { sta[++ttop]=(int)(x%),x/=; }while(x);
while(ttop) pr[lp++]=sta[ttop--]+''; pr[lp++]=;
}
inline void reset(int x) { for(register int i=L[x];i<=R[x];++i) a[i]=rid[x][pos[i]]; }
inline void change(int bel,int x,int y) {
int uid=id[bel][x];id[bel][y]=uid,rid[bel][uid]=y,id[bel][x]=;
}
inline void build(int x) {
for(register int i=;i<=p;++i) id[x][rid[x][i]]=;
for(register int i=L[x],idx=;i<=R[x];++i)
if(!id[x][a[i]])
id[x][a[i]]=++idx,rid[x][idx]=a[i];
for(register int i=L[x];i<=R[x];++i) pos[i]=id[x][a[i]];
}
inline void rebuild(int l,int x,int y) {
for(register int i=bl[l];i<=bl[n];++i) {
s2[i][x]+=s2[i-][x],s2[i][y]+=s2[i-][y];
s1[i][bl[x]]+=s1[i-][bl[x]],s1[i][bl[y]]+=s1[i-][bl[y]];
}
}
inline void modify(int l,int r,int x,int y) {
if(s2[bl[r]][x]-s2[bl[l]-][x]==) return ;
for(int i=bl[n];i>=bl[l];--i) {
s2[i][x]-=s2[i-][x],s2[i][y]-=s2[i-][y];
s1[i][bl[x]]-=s1[i-][bl[x]],s1[i][bl[y]]-=s1[i-][bl[y]];
}
if(bl[l]==bl[r]) {
reset(bl[l]);
for(int i=l;i<=r;++i)
if(a[i]==x) {
a[i]=y;
--s2[bl[l]][x],++s2[bl[l]][y];
--s1[bl[l]][bl[x]],++s1[bl[l]][bl[y]];
}
build(bl[l]),rebuild(l,x,y);return ;
}
reset(bl[l]),reset(bl[r]);
for(int i=l;i<=R[bl[l]];++i)
if(a[i]==x) {
a[i]=y;
--s2[bl[l]][x],++s2[bl[l]][y];
--s1[bl[l]][bl[x]],++s1[bl[l]][bl[y]];
}
for(int i=L[bl[r]];i<=r;++i)
if(a[i]==x) {
a[i]=y;
--s2[bl[r]][x],++s2[bl[r]][y];
--s1[bl[r]][bl[x]],++s1[bl[r]][bl[y]];
}
build(bl[l]),build(bl[r]);
for(int i=bl[l]+;i<bl[r];++i) {
if(!s2[i][x]) continue;
if(s2[i][y]) {
reset(i);
for(int j=L[i];j<=R[i];++j)
if(a[j]==x) {
a[j]=y;
--s2[i][x],++s2[i][y];
--s1[i][bl[x]],++s1[i][bl[y]];
}
build(i);
}
else {
s1[i][bl[y]]+=s2[i][x],s1[i][bl[x]]-=s2[i][x];
s2[i][y]+=s2[i][x],s2[i][x]=;
change(i,x,y);
}
}
rebuild(l,x,y);
}
inline int ask(int l,int r,int k) {
int ans=,sum=;
if(bl[l]==bl[r]) {
reset(bl[l]);for(int i=l;i<=r;++i) vec[i]=a[i];
nth_element(vec+l,vec+l+k-,vec+r+),ans=vec[l+k-];
for(int i=l;i<=r;++i) vec[i]=; return ans;
}
reset(bl[l]),reset(bl[r]);
for(int i=l;i<=R[bl[l]];++i) ++vec[a[i]],++v2[bl[a[i]]];
for(int i=L[bl[r]];i<=r;++i) ++vec[a[i]],++v2[bl[a[i]]];
for(int i=;i<=bl[N-];++i) {
if(sum+v2[i]+s1[bl[r]-][i]-s1[bl[l]][i]>=k) {
for(int j=(i-)*p+;j<=i*p;j++) {
if(vec[j]+s2[bl[r]-][j]-s2[bl[l]][j]+sum>=k) { ans=j;goto FLAG; }
else sum+=vec[j]+s2[bl[r]-][j]-s2[bl[l]][j];
}
}
else sum+=v2[i]+s1[bl[r]-][i]-s1[bl[l]][i];
}
FLAG:
for(int i=l;i<=R[bl[l]];++i) --vec[a[i]],--v2[bl[a[i]]];
for(int i=L[bl[r]];i<=r;++i) --vec[a[i]],--v2[bl[a[i]]];
return ans;
}
int main() {
read(n),read(m),p=sqrt(N)+;
for(int i=;i<N;++i) bl[i]=(i-)/p+;
for(int i=;i<=n;++i) read(a[i]);
for(int i=;i<=bl[n];++i)
L[i]=(i-)*p+,R[i]=i*p;R[bl[n]]=n;
for(int x=;x<=bl[n];++x) build(x);
for(int x=;x<=bl[n];++x) {
for(int i=;i<N;++i) s2[x][i]=s2[x-][i];
for(int i=;i<=bl[N-];++i) s1[x][i]=s1[x-][i];
for(int i=L[x];i<=R[x];++i) ++s1[x][bl[a[i]]],++s2[x][a[i]];
}
for(;m;--m) {
int opt,x,y;read(opt),read(x),read(y);
if(opt==) {int z,w;read(z),read(w),modify(x,y,z,w);}
else {int k;read(k),print(ask(x,y,k));}
}
pr[--lp]='\0'; puts(pr);
return ;
}
[Ynoi2018]未来日记的更多相关文章
- [Ynoi2018]未来日记(分块)
分块神题. 看了一会儿题解,看懂了思路,然后写了两个小时,调了一个多小时,好多地方写错了. 我们考虑对序列和值域都分块.\(sum1[i][j]\) 表示前 \(i\) 个块,第 \(j\) 块值域有 ...
- 「Ynoi2018」未来日记
「Ynoi2018」未来日记 区间x->y,kth值... 不管了,先序列分块... 查询 第k值,假定知道每个数的权值,对值域分块. 对于整块,维护前\(i\)个块当中,值域在\(j\)块里以 ...
- ynoi2018
题解: 全分块是啥操作啊.. 而且都好难.. 1.未来日记 这个比较简单 对每个块开个线段树维护权值 $n\sqrt{n}logn$ 这个会炸空间 并不能做... 但还是说一下做法 首先考虑分块 然后 ...
- [Ynoi2018]五彩斑斓的世界
题目描述 二阶堂真红给了你一个长为n的序列a,有m次操作 1.把区间[l,r]中大于x的数减去x 2.查询区间[l,r]中x的出现次数 题解 做YNOI真**爽... 我们发现这道题的操作非常诡异,把 ...
- [Ynoi2018]末日时在做什么?有没有空?可以来拯救吗?
这道题真的超级...毒瘤 + 卡常 + 耗 RP 啊... 传送门 noteskey 题解看 shadowice 大仙 的 code 如果发现自己 T 掉了,别心急,洗把脸再交一遍试试... //by ...
- 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]
洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...
- 【bzoj4810】【ynoi2018】由乃的玉米田
4810: [Ynoi2017]由乃的玉米田 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1090 Solved: 524[Submit][Sta ...
- 【洛谷5398】[Ynoi2018]GOSICK(二次离线莫队)
题目: 洛谷 5398 当我刚学莫队的时候,他们告诉我莫队能解决几乎所有区间问题: 现在,当我发现一个区间问题似乎难以用我所了解的莫队解决的时候,他们就把这题的正解叫做 XXX 莫队.--题记 (以上 ...
- 洛谷P5398 [Ynoi2018]GOSICK(二次离线莫队)
题面 传送门 题解 维包一生推 首先请确保您会二次离线莫队 那么我们现在的问题就是怎么转移了,对于\(i\)和前缀\([1,r]\)的贡献,我们拆成\(b_i\)和\(c_i\)两部分,其中\(b_i ...
随机推荐
- python基础之作业1---用户登录
作业:编写登陆接口 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 import sys, os, getpass os.system('clear')i = 0while i < 3: ...
- Python with open as函数
可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件. 当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入. 只有调用close ...
- Python3 open函数
Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError. 注意:使用 open() 方法一定要保证关闭 ...
- java_jsp和servlet中乱码问题
- 使用kermit通过串口升级uboot
在开发板的启动选项中看到如下两行: 7: Load Boot Loader code then write to Flash via Serial. 9: Load Boot Loader code ...
- clusterware启动顺序——OHASD
Clusterware启动顺序 [root@ebsdb1 etc]# crsctl check crs CRS-4638: Oracle High Availability Services is ...
- 微信小程序 画布drawImage实现图片截取
大多数图片都大小不一,选择框的尺寸也是宽高相等的,就会有图片被压缩 解决方法: 1.可以使用画布对图片先进行截取,保存截取图片(用户自己选取,或者指定图片中心区域截取),但是对于多张图片手动截取,会影 ...
- 运行 vue 报node错
当报错 为这样时: 执行--npm install node-sass 即可
- org.apache.commons.lang.exception.NestableRuntimeException
jar包不全 附上一个好的的博客链接→
- JS 删除Array对象中的元素。
var idTemp=new Array(); var nameTemp = new Array(); nameTemp.splice($.inArray(“1”, nameTemp),1); idT ...