博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「Ynoi2018」未来日记
阅读量:4704 次
发布时间:2019-06-10

本文共 4308 字,大约阅读时间需要 14 分钟。

区间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
#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<<' '<
<<"___"<
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<

转载于:https://www.cnblogs.com/klauralee/p/10925775.html

你可能感兴趣的文章
IT常用单词
查看>>
拓扑排序
查看>>
NYOJ--32--SEARCH--组合数
查看>>
JMS
查看>>
gulpfile 压缩模板
查看>>
【34.14%】【BZOJ 3110】 [Zjoi2013]K大数查询
查看>>
【 henuacm2016级暑期训练-动态规划专题 A 】Cards
查看>>
第五篇:白话tornado源码之褪去模板的外衣
查看>>
设备常用框架framework
查看>>
bootstrap模态框和select2合用时input无法获取焦点(转)
查看>>
MockObject
查看>>
BZOJ4516: [Sdoi2016]生成魔咒(后缀自动机)
查看>>
查看手机已经记住的WIFI密码
查看>>
最新版IntelliJ IDEA2019 破解教程(2019.08.07-情人节更新)
查看>>
C# 两个datatable中的数据快速比较返回交集或差集
查看>>
关于oracle样例数据库emp、dept、salgrade的mysql脚本复杂查询分析
查看>>
adb shell am 的用法
查看>>
iOS10 UI教程视图和子视图的可见性
查看>>
FindChildControl与FindComponent
查看>>
中国城市json
查看>>