「Ynoi2018」未来日记
「Ynoi2018」未来日记
区间x->y,kth值...
不管了,先序列分块...
查询
第k值,假定知道每个数的权值,对值域分块。
对于整块,维护前\(i\)个块当中,值域在\(j\)块里以及值为\(j\)的数的个数,可以方便的询问。
对于边角,直接记值域在\(j\)块里以及值为\(j\)的数的个数,显然\(o(\sqrt n)\)。
那么接下来只要先按值域块扫,确定第k值在哪个值域块内,然后块内扫一遍,复杂度\(o(\sqrt n)\)。
修改
对于边角,大力重构,暴力修改 前\(i\)个块当中,值域在\(j\)块里以及值为\(j\)的数的个数。
对于整块,可以维护一个并查集,每个点指向相同权值的位置,用top数组记录每种权值的并查集顶端位置。然后x->y就很轻松了对吧...从左到右逐块累加,修改 前\(i\)块 值域在\(j\)块里以及值为\(j\)的数的个数。
总体复杂度\(o((n+m) \sqrt n)\)。
#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
bool cur1;
char buf[10000000],*p1=buf,*p2=buf;
#define Getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++
void in(int &r) {
static char c;
r=0;
while(c=Getchar(),c<48);
do r=(r<<1)+(r<<3)+(c^48);
while(c=Getchar(),c>47);
}
const int mn=100005;
const int BLK1=290;
const int BLK2=320;
int n,K,K1,val[mn],F[BLK2][BLK1],T[mn][BLK1];
//F[i][j] 值域i块,在前j块里的数个数
//T[i][j] 值i,在前j块里的数个数
int fa[mn];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int last[mn],top[BLK1][mn];
#define get_val(x) val[find(x)]
int rebuild(int id,int l1,int r1,int x,int y){
int l=K*id,r=min(K*id+K-1,n),ct=0;
int *tp=top[id];
rep(q,l,r)val[q]=get_val(q),tp[val[q]]=0;
rep(q,l,r){
if(q>=l1&&q<=r1&&val[q]==x)val[q]=y,++ct;
fa[q]=(!last[val[q]]?(tp[val[q]]=q+1,last[val[q]]=q+1):last[val[q]])-1;
}
rep(q,l,r)last[val[q]]=0;
return ct;
}
void cg(int id,int v,int v1,int num){
int *F1=F[v/K1],*F2=F[v1/K1],*T1=T[v],*T2=T[v1];
rep(q,id,n/K){
F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
}
}
void change(int l,int r,int fr,int to){
if(fr==to)return;
int l_id=l/K,r_id=r/K;
if(l_id==r_id){
int ct=rebuild(l_id,l,r,fr,to);
cg(l_id,fr,to,ct);
}else{
int *td,*F1=F[fr/K1],*F2=F[to/K1],*T1=T[fr],*T2=T[to],num=0;
int ct=rebuild(l_id,l,l_id*K+K-1,fr,to);
rep(q,l_id,r_id-1){
F1[q]-=ct,F2[q]+=ct,T1[q]-=ct,T2[q]+=ct;
}
ct+=rebuild(r_id,r_id*K,r,fr,to);
int ld=T1[l_id+1]-T1[l_id];
rep(q,l_id+1,r_id-1){
num+=ld;
ld=T1[q+1]-T1[q];
F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
td=top[q];
if(td[fr]){
if(td[to])fa[td[fr]-1]=td[to]-1;
else val[td[fr]-1]=to,td[to]=td[fr];
td[fr]=0;
}
}
num+=ct;
rep(q,r_id,n/K){
F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
}
}
}
int X[BLK2],Y[mn];
int ask(int l,int r,int k){
int l_id=l/K,r_id=r/K;
int ans=0;
if(l_id==r_id){
rep(q,l,r){
int v=get_val(q);
++X[v/K1],++Y[v];
}
for(int q=0;;++q){
if(X[q]>=k){
rep(w,q*K1,q*K1+K1-1){
if(Y[w]>=k){
ans=w;
break;
}
k-=Y[w];
}
break;
}
k-=X[q];
}
rep(q,l,r){
int v=get_val(q);
--X[v/K1],--Y[v];
}
}else{
rep(q,l,l_id*K+K-1){
int v=get_val(q);
++X[v/K1],++Y[v];
}
rep(q,r_id*K,r){
int v=get_val(q);
++X[v/K1],++Y[v];
}
for(int q=0;;++q){
int v=F[q][r_id-1]-F[q][l_id]+X[q];
if(v>=k){
rep(w,q*K1,q*K1+K1-1){
if(T[w][r_id-1]-T[w][l_id]+Y[w]>=k){
ans=w;
break;
}
k-=T[w][r_id-1]-T[w][l_id]+Y[w];
}
break;
}
k-=v;
}
rep(q,l,l_id*K+K-1){
int v=get_val(q);
--X[v/K1],--Y[v];
}
rep(q,r_id*K,r){
int v=get_val(q);
--X[v/K1],--Y[v];
}
}
return ans;
}
void init(){
rep(q,0,n)fa[q]=q;
rep(q,0,n/K){
int *tp=top[q];
rep(w,q*K,min(n,q*K+K-1)){
fa[w]=(!last[val[w]]?(tp[val[w]]=w+1,last[val[w]]=w+1):last[val[w]])-1;
}
rep(w,q*K,min(n,q*K+K-1))last[val[w]]=0,++F[val[w]/K1][q],++T[val[w]][q];
if(q){
rep(w,0,100000/K1)F[w][q]+=F[w][q-1];
rep(w,0,100000)T[w][q]+=T[w][q-1];
}
}
}
bool cur2;
int main(){
// cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
in(n);
K=sqrt(n)*1.1+1,K1=320;
--n;
int m,ty,a,b,x,y;
in(m);
rep(q,0,n)in(val[q]);
init();
while(m--){
in(ty),in(a),in(b),in(x);
if(ty==1)in(y),change(a-1,b-1,x,y);
else printf("%d\n",ask(a-1,b-1,x));
}
return 0;
}
「Ynoi2018」未来日记的更多相关文章
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
- 「2014-3-18」multi-pattern string match using aho-corasick
我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...
- 「2014-3-17」C pointer again …
记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...
- 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance
提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...
随机推荐
- 实现golang io.Writer支持按照天为单位分割日志
golang中的日志不支持按照天分割,很多开源的日志包都是只支持按照文件大小分割日志,不太利于生产环境中的使用.因此我实现了timewriter,支持: 实现按照天为单位分割日志,可以完美支持gola ...
- 大二 mysql高级+html响应式+Java高级50道试题
1.CSS3中过渡属性 transition-timing-function的值包括哪些 A. ease B. inline C. ease-in D. easeout 答案:A,C 解析:过渡属性 ...
- 编写Java程序,中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝参见玉帝,而每一天参
查看本章节 查看作业目录 需求说明: 中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝 ...
- python 根据传进来的参数,动态拼接sql
根据传进来的参数,动态拼接sql,可用于实现一个方法,有些字段不确定,又用到的情况,如查询,三个查询条件,有的时候只用到一个查询条件,其他用不到则不需要拼接 def show_runjob_detai ...
- python 中的省略号
在查看django源码时遇到下列内容:sweat: 这个省略号是什么意思? 来自为知笔记(Wiz)
- 设置Linux的一些文本输出方式
更新一下yum咯 yum install -y epel-release 火车 sudo yum install sl $ sl 放火 sudo yum install libaa-bin 小老鼠 s ...
- 第10组 Beta冲刺 总结(组长)
1.基本情况 组长博客链接:https://www.cnblogs.com/cpandbb/p/14050808.html 答辩总结: ·因为alpha阶段的产品做得偏离了方向,所以beta冲刺大家非 ...
- 第51篇-SharedRuntime::generate_native_wrapper()生成编译入口
当某个native方法被调用时,一开始它会从解释入口进入,也就是我之前介绍的.由InterpreterGenerator::generate_native_entry()函数生成的入口例程.在这个例程 ...
- Android官方文档翻译 六 1.4Starting Another Activity
Starting Another Activity 开启另一个Activity This lesson teaches you to 这节课教给你: Respond to the Send Butto ...
- MATLAB中插值算法实现
%%%1.M文件%(1).以往少的程序可以在命令行窗口进行编码,但大量的程序编排到命令行窗口,%会有造成乱码的危险.(2).如果将命令编成程序存储在一个文件中(M文件),依次运行文件中的命令,则可以重 ...