[Ynoi2018] 未来日记

news/2024/11/13 15:48:20/文章来源:https://www.cnblogs.com/hzoi-Cu/p/18544094

[Ynoi2018] 未来日记

老早之前就想写了,人生中第一道大分块,调了一上午+下午一个小时,对拍了不知道多少万组,终于过了。

\[\Huge{本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常} \]

\[\Huge{快来写快来写快来写快来写快来写快来写快来写快来写快来写快来写快来写} \]

solution

由于是Ynoi,考虑分块

数据范围\(10^5\),加上这么诡异的操作,先想分块。

区间rank让人以为是[Ynoi2017] 由乃打扑克这道题,但是如果按照由乃打扑克的思路这题的操作就做不了了。

分块是有自己复杂度的就是\(O(\sqrt{n})\)而不是\(O(\log n)\)这意味着分块其实和log的数据结构以及二分法并不是很搭(因为分块的结构本质上就不支持二分)如果我们需要强行嵌入\(log\)的数据结构的话在绝大部分情况下都会使复杂度凭空多出个\(log\)来,这在强调常数的根号算法中绝对是致命的。——来自shadowice1984的题解。

所以可以考虑时间复杂度同为\(O(\sqrt{n})\)的块状数组,由于\(V\le 10^5\),考虑对值域分块,具体的,就是记\(s1_{i,j}\)表示前\(i\)个序列块中有多少个数在\(j\)值域块中,\(s2_{i,j}\)表示前\(i\)块中有多少个\(j\),查询时先遍历值域块,确定答案所在值域块的位置,然后再遍历值域块找到答案。

简单的查询就处理完了,那么这个逆天的修改如何处理,有一个经典套路就是用并查集来维护,具体的,记\(rt_{i,x}\)表示第\(i\)块中值为\(x\)的数的代表元,这里我用的是每块中第\(1\)个数的位置。然后用并查集维护位置就可以了,整块就直接令\(rt_{i,y}=\min\{rt_{i,y},rt_{i,x}\}\)即可,考虑散块,仍然考虑暴力修,但是如果每个都修爆炸,只需要重构\(rt_{i,x},rt_{i,y}\)为根的子树就行。

时间复杂度\(O((n+m)\sqrt{n})\),实现优秀,cin/cout关了同步流都能过!!!

挂一个你谷第2优解。

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCALFILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);FILE *ErrFile = freopen("err.err","w",stderr);
#elseFILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
namespace IO{const int size = 1<<24;struct IO{char buf[size],*p1,*p2,obuf[size],*op = obuf;#define gc() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2))?EOF:*p1++)inline void pc(char x){if(__builtin_expect(op - obuf == size,1)) fwrite(obuf,1,size,stdout);*op++ = x;}~IO(){fwrite(obuf,1,op-obuf,stdout);}template<class T>inline void read(T &x){x = 0;char s = gc();for(;s < '0' || '9' < s;s = gc());for(;'0' <= s && s <= '9';s = gc())x = (x<<1)+(x<<3)+(s^48);}template<class T,class... Args>inline void read(T &x,Args&... argc){read(x);read(argc...);}template<class T>inline void write(T x){static int sta[30],top = 0;do sta[++top] = x%10;while(x /= 10);while(top) pc(sta[top--]+'0');}inline void write(char x){pc(x);}template<class T,class... Args>inline void write(T x,Args... argc){write(x);write(argc...);}}io;#define read io.read#define write io.write
}using IO::io;
/*
诶不是,我要处理啥啊。
对于值域块处理1~i中有多少个,然后还要处理每个数。
*/
const int N = 1e5 + 1,SN = N/310,V = 1e5 + 1,SV = N/310,RV = 1e5,cjs = 123;
int n,m,a[N];
int L1[SN],R1[SN],p1[N],lens,sizs;
int L2[SV],R2[SV],p2[V],lenv,sizv;
int s1[SN][SV];//前i块中有多少个数在j块中
int s2[SN][V];//前i块中有多少个j
int s3[SN][V];//第i块中有多少个j
int rt[SN][V],fa[N];
int ct1[SV],ct2[V];//查询时用来记录散块
inline int get_fa(int x){while(x^fa[x]) x = fa[x] = fa[fa[x]];return x;}
inline void Merge(int x,int y){if(x > y) swap(x,y);fa[y] = x;}
//将y并到x中,顺序有关。 
inline void upd(int l,int r,int x,int y){int p = p1[l],q = p1[r],px = p2[x],py = p2[y],sum = 0;auto rbuild = [&](int p,int l,int r){if(!s3[p][x]) return 0;int res = 0,ff = rt[p][x];vector<int> sonx,sony;rep(i,L1[p],R1[p],1){if(get_fa(i) == rt[p][x]){if(i < l || i > r) sonx.emplace_back(i);else sony.emplace_back(i),++res;}if(fa[i] == rt[p][y]) sony.emplace_back(i);}rt[p][x] = rt[p][y] = 0;for(auto i:sonx){if(!rt[p][x]) rt[p][x] = fa[i] = i;else fa[i] = rt[p][x];a[i] = x;}for(auto i:sony){if(!rt[p][y]) rt[p][y] = fa[i] = i;else fa[i] = rt[p][y];a[i] = y;}s3[p][x] -= res,s3[p][y] += res;sum += res;return res;};if(p == q){int res = rbuild(p,l,r);if(!res) return;rep(i,p,sizs,1){s1[i][px] -= res;s1[i][py] += res;s2[i][x] -= res,s2[i][y] += res;}return;}rbuild(p,l,R1[p]);s1[p][px] -= sum;s1[p][py] += sum;s2[p][x] -= sum,s2[p][y] += sum;rep(i,p+1,q-1,1){if(s3[i][x]){if(!rt[i][y]) rt[i][y] = rt[i][x],a[rt[i][x]] = y;else Merge(rt[i][y],rt[i][x]);fa[rt[i][y] = get_fa(rt[i][y])] = rt[i][y];rt[i][x] = 0;a[get_fa(rt[i][y])] = y;sum += s3[i][x],s3[i][y] += s3[i][x],s3[i][x] = 0;}s1[i][px] -= sum,s1[i][py] += sum;s2[i][x] -= sum,s2[i][y] += sum;}rbuild(q,L1[q],r);s1[q][px] -= sum;s1[q][py] += sum;s2[q][x] -= sum,s2[q][y] += sum;if(!sum) return;rep(i,q+1,sizs,1){s1[i][px] -= sum;s1[i][py] += sum;s2[i][x] -= sum,s2[i][y] += sum;}
}
inline int qry(int l,int r,int k){int p = p1[l],q = p1[r];if(p == q){vector<int> res;rep(i,l,r,1) res.emplace_back(a[get_fa(i)]);nth_element(res.begin(),res.begin()+k-1,res.end());return *(res.begin()+k-1);}rep(i,l,R1[p],1) ++ct2[a[get_fa(i)]],++ct1[p2[a[get_fa(i)]]];rep(i,L1[q],r,1) ++ct2[a[get_fa(i)]],++ct1[p2[a[get_fa(i)]]];int sum = 0,pos = 0,ans = 0;rep(i,1,sizv,1){sum += ct1[i] + s1[q-1][i] - s1[p][i];if(sum >= k){sum -= ct1[i] + s1[q-1][i] - s1[p][i];pos = i;break;}}rep(j,L2[pos],R2[pos],1){if(sum + ct2[j] + s2[q-1][j] - s2[p][j] >= k){ans = j;break;}sum += ct2[j] + s2[q-1][j] - s2[p][j];}rep(i,l,R1[p],1) ct2[a[get_fa(i)]]--,ct1[p2[a[get_fa(i)]]]--;rep(i,L1[q],r,1) ct2[a[get_fa(i)]]--,ct1[p2[a[get_fa(i)]]]--;return ans;
}
inline void solve(){read(n,m);rep(i,1,n,1) read(a[i]),fa[i] = i;lens = 500,sizs = n/lens;rep(i,1,sizs,1) L1[i] = R1[i-1]+1,R1[i] = i*lens;if(R1[sizs] < n) sizs++,L1[sizs] = R1[sizs-1]+1,R1[sizs] = n;lenv = sqrt(RV),sizv = RV/lenv;rep(i,1,sizv,1) L2[i] = R2[i-1]+1,R2[i] = i*lenv;if(R2[sizv] < RV) sizv++,L2[sizv] = R2[sizv-1]+1,R2[sizv] = RV;rep(i,1,sizv,1) rep(j,L2[i],R2[i],1) p2[j] = i;rep(i,1,sizs,1){rep(j,L1[i],R1[i],1){p1[j] = i;s1[i][p2[a[j]]]++;s2[i][a[j]]++;s3[i][a[j]]++;if(!rt[i][a[j]]) rt[i][a[j]] = j;else fa[j] = rt[i][a[j]];}rep(j,1,sizv,1) s1[i][j] += s1[i-1][j];rep(j,1,RV,1) s2[i][j] += s2[i-1][j];}rep(test,1,m,1){int op,l,r,x,y;read(op);if(op ^ 2) read(l,r,x,y),(x^y)?upd(l,r,x,y):void();else read(l,r,x),write(qry(l,r,x),'\n');}
}
signed main(){solve();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832995.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(系列十一)Vue3框架中路由守卫及请求拦截(实现前后端交互)

说明该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。说明:OverallAuth2.0 是一个简单、易懂、功能强大的权限+可视化流程管理系统。 友情提醒:本篇文章是属于系列文章,…

MIGO DUMP LCX_RAP_EVENT_RUNTIME CL_RAP_EVENT_MANAGER==========CP

MIGO 收货时发生DUMP运行事务代码:SBGRFCCONF 创建入站目标输入目标BGPF 保存即可TRANSLATE with xEnglishArabic Hebrew PolishBulgarian Hindi PortugueseCatalan Hmong Daw RomanianChinese Simplified Hungarian RussianChinese Traditional Indonesian SlovakCzech Ital…

非煤矿山算法智慧矿山一体机提升机危险区域违规闯入识别边坡监测预警系统详述

在矿山行业中,安全始终是最为关键的议题。随着智能化技术的发展,智慧矿山一体机应运而生,它专为矿山安全监控和管理设计,集成了多种智能化功能,以提升矿山的安全监管能力和生产效率。这款设备不仅能够满足矿山场景下的视频智能化建设需求,还能够通过边缘计算技术实现对矿…

全国职业院校技能大赛

老师说目前这个是省赛,预计12月参加,如果要准备的话,预计要有一个月的时间准备我看了一下往年的题目,确实是平常老师跟我们讲的那种术语什么的

Hadoop搭建集群

不知道为什么会出现这样的结果

使用idea创建Sping Boot 项目 发现不能使用JAVA版本是8或者11版本只能用17版本已经更高

接下来需要一个骚操作, 官方地址: https://start.spring.io阿里云脚手架地址:https://start.aliyun.com/

[题解]P3225 [HNOI2012] 矿场搭建

P3225 [HNOI2012] 矿场搭建 挖煤点坍塌相当于把该点和与其相连的边在图上删掉。 借用wjyyy的题解,我们定义“叶子连通块”为“只包含\(1\)个割点的点双连通分量”,“非叶子连通块”为“包含\(\ge 2\)个割点的点双连通分量”。 如下图,橙色点是割点,红色框圈出的是点双,加粗…

DDCA —— 内存架构和子系统内存控制器

Digital Design and Computer Architecture Lecture21的学习笔记,介绍内存架构和子系统、内存控制器,并详细介绍了DRAM的内部结构。1. 内存架构和子系统 1.1 如何控制访问?访问控制:存储单元的访问是通过 访问晶体管(access transistors) 进行控制的。访问晶体管像开关一…

ubuntu上安装 NVIDIA GeForce RTX 4090驱动

背景 ai服务器上安装完ubuntu系统后,需要安装NVIDIA显卡驱动 官网驱动下载https://www.nvidia.cn/drivers/details/235646/驱动安装 1.卸载原有驱动 sudo apt remove --purge nvidia*2.备份 sudo cp /etc/modprobe.d/blacklist.conf /etc/modprobe.d/blacklist.conf_bak 3.末尾…

springboot将文件处理成压缩文件

前言 在工作我们经常会出现有多个文件,为了节省资源会将多个文件放在一起进行压缩处理;为了让大家进一步了解我先将springboot处理的方法总结如下,有不到之处敬请大家批评指正! 一、文件准备:https://qnsc.oss-cn-beijing.aliyuncs.com/crmebimage/public/product/2024/11…

CMDB平台(进阶篇):CMDB的构建指南(一)

CMDB(配置管理数据库)的构建是一个复杂而细致的过程,其中组建项目团队和定义项目是至关重要的初始阶段。以下是根据高权威性来源整理的,关于这两个阶段的详细指南: 一、组建项目团队 团队角色与技能: 选择的团队必须具备相应的技能、经验、知识去解释、设计和实施一个CMD…

出差及报销问题

出差问题 报销问题 一、提交报销申请提交报销申请在应用导航的 ERP门户系统 中,选择我要报账在保障服务平台--单据管理--全部单据里选择--差旅费报账单(新)报销申请单填写选择想要报销的出差审批单上传想要报销的发票后点击下一步填写基本信息影像张数: 上传附件图片数量。…