[Ynoi2018]未来日记(分块)
分块神题。
看了一会儿题解,看懂了思路,然后写了两个小时,调了一个多小时,好多地方写错了。
我们考虑对序列和值域都分块。\(sum1[i][j]\) 表示前 \(i\) 个块,第 \(j\) 块值域有几个数,\(sum2[i][j]\) 表示前 \(i\) 个块,值为 \(j\) 有几个数,\(id[i][j]\) 表示第 \(i\) 块值为 \(j\) 的编号,\(mp[i][j]\) 表示第 \(i\) 块编号为 \(j\) 值为多少,这样空间正好开的下。
对于修改操作,我们考虑边角暴力。在整块中若只有 \(x\) 那么直接修改,若又有 \(y\) 的话就暴力重构。每次重构整块中不同的数的数目会 \(-1\),一个块最多被重构 \(\sqrt{n}\) 块,所以时间复杂度保证为 \(O(n\sqrt{n})\)
对于询问操作,我们利用 \(sum1\) 和 \(sum2\) 可以在 \(O(\sqrt{n})\) 得到。
时间复杂度 \(O(n\sqrt{n})\),空间复杂度 \(O(n\sqrt{n})\)
洛谷加了 \(fread,fwrite\) 才卡过去,空间差点 \(MLE\)。。。
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
const int maxblo=317;
const int lim=100000;
int n,m,blo,a[maxn],pos[maxn],bl[maxn],L[maxn],R[maxn];
int v1[maxn],v2[maxn],sum1[maxblo][maxblo],sum2[maxblo][maxn],id[maxblo][maxn],mp[maxblo][maxblo];
namespace FastIO{
#define gc() (iS==iT?(iT=(iS=ibuff)+fread(ibuff,1,SIZ,stdin),(iS==iT?EOF:*iS++)):*iS++)
const int SIZ=1<<21|1;
char *iS,*iT,ibuff[SIZ],obuff[SIZ],*oS=obuff,*oT=oS+SIZ-1,fu[110],c;int fr;
inline void out(){
fwrite(obuff,1,oS-obuff,stdout);
oS=obuff;
}
template <class T>
inline void read(T &x){
x=0;T y=1;
for(c=gc();(c>'9'||c<'0')&&c!='-';c=gc());
c=='-'?y=-1:x=(c&15);
for(c=gc();c>='0'&&c<='9';c=gc()) x=x*10+(c&15);
x*=y;
}
template <class T>
inline void print(T x,char text='\n'){
if(x<0) *oS++='-',x*=-1;
if(x==0) *oS++='0';
while(x) fu[++fr]=x%10+'0',x/=10;
while(fr) *oS++=fu[fr--];
*oS++=text;out();
}
}
using namespace FastIO;
inline void reset(int x){
for(int i=L[x];i<=R[x];i++) a[i]=mp[x][pos[i]];
}
inline void change(int bel,int x,int y){
int last=id[bel][x];id[bel][y]=last;
mp[bel][last]=y;id[bel][x]=0;
}
inline void build(int x){
for(int i=1;i<=blo;i++) id[x][mp[x][i]]=0;
int ind=0;
for(int i=L[x];i<=R[x];i++)
if(!id[x][a[i]]) id[x][a[i]]=++ind,mp[x][ind]=a[i];
for(int i=L[x];i<=R[x];i++) pos[i]=id[x][a[i]];
}
inline void rebuild(int l,int x,int y){
for(int i=bl[l];i<=bl[n];i++){
sum1[i][bl[x]]+=sum1[i-1][bl[x]];
sum1[i][bl[y]]+=sum1[i-1][bl[y]];
sum2[i][x]+=sum2[i-1][x];
sum2[i][y]+=sum2[i-1][y];
}
}
inline void modify(int l,int r,int x,int y){
if(sum2[bl[r]][x]==sum2[bl[l]-1][x]) return ;
for(int i=bl[n];i>=bl[l];i--){
sum1[i][bl[x]]-=sum1[i-1][bl[x]];
sum1[i][bl[y]]-=sum1[i-1][bl[y]];
sum2[i][x]-=sum2[i-1][x];
sum2[i][y]-=sum2[i-1][y];
}
if(bl[l]==bl[r]){
reset(bl[l]);
for(int i=l;i<=r;i++)
if(a[i]==x){
a[i]=y;
sum1[bl[l]][bl[x]]--;
sum1[bl[l]][bl[y]]++;
sum2[bl[l]][x]--;
sum2[bl[l]][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;
sum1[bl[l]][bl[x]]--;
sum1[bl[l]][bl[y]]++;
sum2[bl[l]][x]--;
sum2[bl[l]][y]++;
}
for(int i=L[bl[r]];i<=r;i++)
if(a[i]==x){
a[i]=y;
sum1[bl[r]][bl[x]]--;
sum1[bl[r]][bl[y]]++;
sum2[bl[r]][x]--;
sum2[bl[r]][y]++;
}
build(bl[l]);build(bl[r]);
for(int i=bl[l]+1;i<bl[r];i++){
if(!sum2[i][x]) continue;
if(sum2[i][y]){
reset(i);
for(int j=L[i];j<=R[i];j++)
if(a[j]==x){
a[j]=y;
sum1[i][bl[x]]--;
sum1[i][bl[y]]++;
sum2[i][x]--;
sum2[i][y]++;
}
build(i);
}
else {
sum1[i][bl[x]]-=sum2[i][x];
sum1[i][bl[y]]+=sum2[i][x];
sum2[i][y]+=sum2[i][x];
sum2[i][x]=0;
change(i,x,y);
}
}
rebuild(l,x,y);
}
inline int query(int l,int r,int k){
if(bl[l]==bl[r]){
reset(bl[l]);
for(int i=l;i<=r;i++) v1[i]=a[i];
nth_element(v1+l,v1+l+k-1,v1+r+1);
int ans=v1[l+k-1];
for(int i=l;i<=r;i++) v1[i]=0;
return ans;
}
reset(bl[l]);reset(bl[r]);
for(int i=l;i<=R[bl[l]];i++) v1[bl[a[i]]]++,v2[a[i]]++;
for(int i=L[bl[r]];i<=r;i++) v1[bl[a[i]]]++,v2[a[i]]++;
for(int i=1;i<=bl[lim];i++){
if(k>v1[i]+sum1[bl[r]-1][i]-sum1[bl[l]][i]) k-=v1[i]+sum1[bl[r]-1][i]-sum1[bl[l]][i];
else {
for(int j=(i-1)*blo+1;j<=i*blo;j++){
if(k>v2[j]+sum2[bl[r]-1][j]-sum2[bl[l]][j]) k-=v2[j]+sum2[bl[r]-1][j]-sum2[bl[l]][j];
else {
for(int x=l;x<=R[bl[l]];x++) v1[bl[a[x]]]--,v2[a[x]]--;
for(int x=L[bl[r]];x<=r;x++) v1[bl[a[x]]]--,v2[a[x]]--;
return j;
}
}
}
}
}
int main()
{
read(n),read(m);blo=sqrt(lim)+1;
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=lim;i++){
bl[i]=(i-1)/blo+1;
if(bl[i]!=bl[i-1]) L[bl[i]]=i,R[bl[i-1]]=i-1;
}
R[bl[n]]=n;
for(int i=1;i<=bl[n];i++) build(i);
for(int x=1;x<=bl[n];x++){
for(int i=1;i<=bl[lim];i++) sum1[x][i]=sum1[x-1][i];
for(int i=1;i<=lim;i++) sum2[x][i]=sum2[x-1][i];
for(int i=L[x];i<=R[x];i++) sum1[x][bl[a[i]]]++,sum2[x][a[i]]++;
}
int op,l,r,x,y;
while(m--){
read(op),read(l),read(r),read(x);
if(op==1) read(y),modify(l,r,x,y);
else print(query(l,r,x));
}
return 0;
}
[Ynoi2018]未来日记(分块)的更多相关文章
- [Ynoi2018]未来日记
"望月悲叹的最初分块" (妈呀这名字好中二啊(谁叫我要用日本轻小说中的东西命名真是作死)) 这里就直接挂csy的题解了,和我的不太一样,但是大概思路还是差不多的,我的做法是和“五彩 ...
- 「Ynoi2018」未来日记
「Ynoi2018」未来日记 区间x->y,kth值... 不管了,先序列分块... 查询 第k值,假定知道每个数的权值,对值域分块. 对于整块,维护前\(i\)个块当中,值域在\(j\)块里以 ...
- 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]
洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...
- [YNOI2018]五彩斑斓的世界&CF896E(分块+并查集)
由于晚上比赛二连(Atcoder&codeforces),外加复习学考,所以暂时没时间写了. 贴个O(n√n)的分块代码,洛谷和cf上都过了,但垃圾bzoj卡不过去,不改了. #include ...
- ynoi2018
题解: 全分块是啥操作啊.. 而且都好难.. 1.未来日记 这个比较简单 对每个块开个线段树维护权值 $n\sqrt{n}logn$ 这个会炸空间 并不能做... 但还是说一下做法 首先考虑分块 然后 ...
- PHP搭建大文件切割分块上传功能
背景 在网站开发中,文件上传是很常见的一个功能.相信很多人都会遇到这种情况,想传一个文件上去,然后网页提示"该文件过大".因为一般情况下,我们都需要对上传的文件大小做限制,防止出现 ...
- POJ2104 K-th Number [分块做法]
传送:主席树做法http://www.cnblogs.com/candy99/p/6160704.html 做那倒带修改的主席树时就发现分块可以做,然后就试了试 思想和教主的魔法差不多,只不过那个是求 ...
- HDU 4467 分块
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...
- 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...
随机推荐
- eclipse安装提要
svn 插件安装http://subclipse.tigris.org/update_1.12.x教程地址http://jingyan.baidu.com/article/f71d60376b4c57 ...
- normalized
共同点:实现规范化,让一个向量保持相同的方向,但它的长度为1.0,如果这个向量太小而不能被规范化,一个零向量将会被返回. 不同点:Vector3.normalized的作特点是当前向量是不改变的并且返 ...
- 2018.12.08 codeforces 914D. Bash and a Tough Math Puzzle(线段树)
传送门 线段树辣鸡题. 题意简述:给出一个序列,支持修改其中一个数,以及在允许自行修改某个数的情况下询问区间[l,r][l,r][l,r]的gcdgcdgcd是否可能等于一个给定的数. 看完题就感觉是 ...
- jquery选择树:CheckTree 插件
在做权限等提交的时候,需要用到选择树.比较了很多插件如:easyUI 树,ztree等等.本来决定自己写,但是到最后还是发现了checkTree这个插件.省了很多事情. 但是在引用过程中还是出现了一些 ...
- php 操作redis 以及几个常用命令
redis-cli -h host -p port -a password 首次进入redis 进行绑定ip和端口号 del key 删除指定key exists key 检查指定key是否存 ...
- 设置vue启动项目后默认显示的页面
通过配置路由,可以设置vue项目启动后默认显示的页面.路由的path设置为path:"/",启动项目后就会显示默认的组件页面. import Vue from 'vue' impo ...
- SVD图片有损压缩测试
注意文件名别保持成svd.m,这样与系统的默认svd程序冲突 图片处理函数生成的三组二维数组对应RGB,处理时保留一组 clear all; close all; clc; a1=imread('C: ...
- 已经安装了客户端,但是cmd输入sqlcmd报错:Sqlcmd:Error:Connection failure.SQL Native Client is not installed correctly
以前安装了sqlserver2008,没有卸载掉,后面又安装了sqlserver2014,所以系统环境变量中既有2008的环境变量的配置,又有2014的环境变量的配置,所以在终端输入sqlcmd时报错 ...
- maven下的经常使用的几个元素以及依赖范围的一些知识
maven的pom.xml配置文件里面的project根节点下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个依赖,每个依赖都可以包含的元素: groupId ...
- 好文推荐系列--------(1)bower---管理你的客户端依赖
好文原文地址:http://segmentfault.com/a/1190000000349555 编者注:我们发现了比较有趣的系列文章<30天学习30种新技术>,准备翻译,一天一篇更新, ...