ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

带插入区间K小值

2022-02-15 18:00:45  阅读:670  来源: 互联网

标签:val la int ++ 插入 小值 区间 pl size


link

题意很明了,就是题目,只不过题目中没说这道题强制在线。

普通情况下可以用平衡树套权值线段树,或者用线段树(树状数组)套个位置平衡树(但我不会写也没有写过)。然而我浏览了一圈讨论之后发现万恶的noip似乎卡了树套树的写法。于是迫不得已学了下块状链表。

块状链表说起来并没有太难,思想很简易,只是代码细节特别多,这也导致我今天下午从三点半开始写一直写到了现在,也就是接近六点。各种bug层出不穷,实在令人感动。主要是查询时for循环里的开关不能取等,然后跳出来后只需自减一次即可。

这道题还用了值域分块,与块状链表一起逼得我不得不小小滴压了压行。

人都写麻了。

#include<cstdio>
#include<cmath>
//#define zczc
const int N=70010;/*值域*/const int S=350;/*值域块数*/const int ks=S;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}wh*=f;return;
}
struct node{int a[S<<1];/*块内数*/int s1[N];/*块间数值前缀和*/int s2[S];/*块间值域块前缀和*/int size,l,r;}a[S<<1];
int cnt,l,r,val,la,s1[N],s2[S],m,n,ms,bl[N];;
void solve1(){
	int pl=1,pr=1,sl,sr,an=0,srr;
	for(;l>a[pl].size;pl=a[pl].r)l-=a[pl].size;
	for(;r>a[pr].size;pr=a[pr].r)r-=a[pr].size;sl=l,sr=r;
	if(pl==pr){
		for(int i=l;i<=r;i++)s1[a[pl].a[i]]++,s2[bl[a[pl].a[i]]]++;
		for(int i=0;val>s2[i];an+=ks,i++)val-=s2[i];an--;
		for(;val>0;)val-=s1[++an];printf("%d\n",la=an);
		for(int i=sl;i<=sr;i++)s1[a[pl].a[i]]--,s2[bl[a[pl].a[i]]]--;return;
	}
	for(;l<=a[pl].size;l++)s1[a[pl].a[l]]++,s2[bl[a[pl].a[l]]]++;
	for(;r;r--)s1[a[pr].a[r]]++,s2[bl[a[pr].a[r]]]++;pr=a[pr].l;
	for(int i=0;val>(srr=s2[i]+(a[pr].s2[i]-a[pl].s2[i]));an+=ks,i++)val-=srr;an--;
	for(;val>0;)val-=(s1[++an]+a[pr].s1[an]-a[pl].s1[an]);printf("%d\n",la=an);pr=a[pr].r;
	for(l=sl;l<=a[pl].size;l++)s1[a[pl].a[l]]--,s2[bl[a[pl].a[l]]]--;
	for(r=sr;r;r--)s1[a[pr].a[r]]--,s2[bl[a[pr].a[r]]]--;return;
}
void solve2(){
	int pl=1;for(;l>a[pl].size;pl=a[pl].r)l-=a[pl].size;
	int data=a[pl].a[l];a[pl].a[l]=val;
	for(;pl;pl=a[pl].r)a[pl].s1[data]--,a[pl].s1[val]++,a[pl].s2[bl[data]]--,a[pl].s2[bl[val]]++;
}
void solve3(){
	int pl=1,las;for(;l>a[pl].size&&pl;pl=a[pl].r)l-=a[pl].size,las=pl;
	if(l&&pl==0)pl=las,l=a[las].size+1;
	for(int i=a[pl].size;i>=l;i--)a[pl].a[i+1]=a[pl].a[i];a[pl].a[l]=val;
	for(int i=pl;i;i=a[i].r)a[i].s1[val]++,a[i].s2[bl[val]]++;a[pl].size++;
	if(a[pl].size>=2*ms){
		++cnt;for(int i=0;i<N;i++)a[cnt].s1[i]=a[pl].s1[i];for(int i=0;i<S;i++)a[cnt].s2[i]=a[pl].s2[i];
		a[cnt].l=pl,a[cnt].r=a[pl].r;a[a[pl].r].l=cnt;a[pl].r=cnt;a[cnt].size=a[pl].size-ms;
		for(int i=1;i<=a[cnt].size;i++)a[cnt].a[i]=a[pl].a[a[pl].size-a[cnt].size+i];a[pl].size-=a[cnt].size;
		for(int i=1;i<=a[cnt].size;i++)a[pl].s1[a[cnt].a[i]]--,a[pl].s2[bl[a[cnt].a[i]]]--;
	}
}

signed main(){
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	read(m);ms=ceil(sqrt(m));for(int i=0;i<N;i++)bl[i]=i/ks;
	for(int i=1,ss=1,now;i<=m;i++){
		read(now);cnt=ss;a[ss].a[++a[ss].size]=now;a[ss].s2[bl[now]]++;a[ss].s1[now]++;
		if(a[ss].size==ms){
			a[ss].r=ss+1;a[ss+1].l=ss;ss++;
			for(int i=0;i<N;i++)a[ss].s1[i]=a[ss-1].s1[i];
			for(int i=0;i<S;i++)a[ss].s2[i]=a[ss-1].s2[i];
		}
	}read(n);char op;
	while(n--){
		char op=getchar();while(op<'A'||op>'Z')op=getchar();
		if(op=='Q'){read(l);read(r);read(val);l^=la,r^=la,val^=la;solve1();}
		if(op=='M'){read(l);read(val);l^=la,val^=la;solve2();}
		if(op=='I'){read(l);read(val);l^=la,val^=la;solve3();}
	}return 0;
}

标签:val,la,int,++,插入,小值,区间,pl,size
来源: https://www.cnblogs.com/dai-se-can-tian/p/15897631.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有