"望月悲叹的最初分块" (妈呀这名字好中二啊(谁叫我要用日本轻小说中的东西命名真是作死))

这里就直接挂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]未来日记的更多相关文章

  1. [Ynoi2018]未来日记(分块)

    分块神题. 看了一会儿题解,看懂了思路,然后写了两个小时,调了一个多小时,好多地方写错了. 我们考虑对序列和值域都分块.\(sum1[i][j]\) 表示前 \(i\) 个块,第 \(j\) 块值域有 ...

  2. 「Ynoi2018」未来日记

    「Ynoi2018」未来日记 区间x->y,kth值... 不管了,先序列分块... 查询 第k值,假定知道每个数的权值,对值域分块. 对于整块,维护前\(i\)个块当中,值域在\(j\)块里以 ...

  3. ynoi2018

    题解: 全分块是啥操作啊.. 而且都好难.. 1.未来日记 这个比较简单 对每个块开个线段树维护权值 $n\sqrt{n}logn$ 这个会炸空间 并不能做... 但还是说一下做法 首先考虑分块 然后 ...

  4. [Ynoi2018]五彩斑斓的世界

    题目描述 二阶堂真红给了你一个长为n的序列a,有m次操作 1.把区间[l,r]中大于x的数减去x 2.查询区间[l,r]中x的出现次数 题解 做YNOI真**爽... 我们发现这道题的操作非常诡异,把 ...

  5. [Ynoi2018]末日时在做什么?有没有空?可以来拯救吗?

    这道题真的超级...毒瘤 + 卡常 + 耗 RP 啊... 传送门 noteskey 题解看 shadowice 大仙 的 code 如果发现自己 T 掉了,别心急,洗把脸再交一遍试试... //by ...

  6. 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]

    洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...

  7. 【bzoj4810】【ynoi2018】由乃的玉米田

    4810: [Ynoi2017]由乃的玉米田 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1090  Solved: 524[Submit][Sta ...

  8. 【洛谷5398】[Ynoi2018]GOSICK(二次离线莫队)

    题目: 洛谷 5398 当我刚学莫队的时候,他们告诉我莫队能解决几乎所有区间问题: 现在,当我发现一个区间问题似乎难以用我所了解的莫队解决的时候,他们就把这题的正解叫做 XXX 莫队.--题记 (以上 ...

  9. 洛谷P5398 [Ynoi2018]GOSICK(二次离线莫队)

    题面 传送门 题解 维包一生推 首先请确保您会二次离线莫队 那么我们现在的问题就是怎么转移了,对于\(i\)和前缀\([1,r]\)的贡献,我们拆成\(b_i\)和\(c_i\)两部分,其中\(b_i ...

随机推荐

  1. IDEA中项目编码格式设置

    自从换成IntelliJ IDEA 之后各种设置就成了问题,这不,在跟另一家公司做对接的时候,他们说我这边的http接口返回的都是乱码, 所有的接口我这边的都是访问过的,这个怎么会,我用360浏览器和 ...

  2. H5样式(个人使用)

    @*定义全局样式*@ <style> body, ul, li, p, h1, h2, h3, h4, h5, h6, hr, span, form, fieldset, table, t ...

  3. Android : Camera之CHI API

    一.CAM CHI API功能介绍: CHI API建立在Google HAL3的灵活性基础之上,目的是将Camera2/HAL3接口分离出来用于使用相机功能,它是一个灵活的图像处理驱动程序(摄像头硬 ...

  4. 表单传参,在action中的参数得不到

    写上面这个的时候,发现传过去的url路径是这样的 在action后面的pro=login得不到. 只需要将method中的get改成post就可以了

  5. QSSP软件一些参数的设置(远震波形合成)

    1.time window, sampling interval 这里需要注意的是两者的和必须是2的n次方,可以写成2047 1; 2046 2,或2047.75 0.25,2047.9 0.1等等 ...

  6. 18-09-11 软件rpm yum rm卸载 和批量删除

    一 在Linux下删除文件用rm命令,具体用法如下: rm [选项] 文件 选项说明: -f -force 忽略不存在的文件,强制删除,无任何提示 -i --interactive 进行交互式地删除 ...

  7. Javascript学习---倒计时

    function fn() { var now = new Date(); // 此时此刻的时间 var old = new Date(2018, 9, 30); // 2018,6,25 var t ...

  8. 基于testng框架的web自动化测试

    package baidutest; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.o ...

  9. 微信小程序:首页设置方法(开发模式,使用模式)与其他相关设置

    小程序开发并不愉快,许多必建的文件不会自动生成,页面之间的跳转没有快捷键,开发者工具显示区域受限……如果谁有对应的解决办法求告知…… 开始的时候每次保存代码,页面都会刷洗重新渲染一次,而且自动跳回首页 ...

  10. 单链表sLinkList类,模板类

    sLinkList模板类,单链表代码 /* 该文件按习惯可以分成.h文件和实现的.cpp文件 */ template <class elemType> class sLinkList { ...