动态区间第k小

题目链接

题意:动态区间第k小就是静态区间第k小加上修改这个功能,静态第k小我们是用主席树做的,但是如果带上修改的功能,主席树保存的是前缀信息,所以说,当修改了一个点的时候,他后面的点都要修改,很明显时间复杂度过不去。所以就用树套树,树状数组套动态开点线段树,树状数组的时间复杂度是logn。这个题写了超久,要不是男神给我debug,估计还要两三天才能写出来。

数组数组的上限是n,不是离散化后的元素个数,因为一共有n个根节点。如果离线做这道题,需要多留一点空间。

动态区间第k小_第1张图片

#include
#define low(x) x&-x
#define mid (l+r)/2
using namespace std;
const int maxn=1e5+100; 
int n,cnt,a[maxn],V[25],S[maxn*210],tot=0,V1[25];
int tot1=0,sz;
int sum[maxn*210],ls[maxn*210],rs[maxn*210],rt[maxn];
struct node{
	char opt[2];
	int ql,qr,k;
}Q[maxn];
void up(int l,int r,int p,int v)
{
	for(int i=1;i<=tot;i++)
	{
		sum[V[i]]+=v;
 	}
	if(l==r)return ;
	if(p<=mid)
	{
		for(int i=1;i<=tot;i++)
		{
			if(!ls[V[i]])ls[V[i]]=++cnt;
			V[i]=ls[V[i]];
		}
		up(l,mid,p,v);
	}
	else 
	{
		for(int i=1;i<=tot;i++)
		{
			if(!rs[V[i]])rs[V[i]]=++cnt;
			V[i]=rs[V[i]];
		}
		up(mid+1,r,p,v);
	}
}
int qu(int l,int r,int k)
{
	if(l==r)return S[l];
	int res=0;
	for(int i=1;i<=tot1;i++)
	{
		res+=sum[ls[V1[i]]];
	}
	for(int i=1;i<=tot;i++)
	{
		res-=sum[ls[V[i]]];
	}
	if(res>=k)
	{
		for(int i=1;i<=tot;i++)
		{
			V[i]=ls[V[i]];
		}
		for(int i=1;i<=tot1;i++)
		{
			V1[i]=ls[V1[i]];
		}
		qu(l,mid,k);
	}
	else 
	{
		for(int i=1;i<=tot;i++)
		{
			V[i]=rs[V[i]];
		}
		for(int i=1;i<=tot1;i++)
		{
			V1[i]=rs[V1[i]];
		}
		qu(mid+1,r,k-res);
	}
}
void modify(int x,int p,int v)
{
	tot=0;
	for(;x<=n;x+=low(x))
	{
		V[++tot]=rt[x];
	}
	up(1,sz,p,v);
}
void _qu(int l,int r,int k)
{
	tot=0,tot1=0;
	for(;l;l-=low(l))
	{
		V[++tot]=rt[l];
	}
	for(;r;r-=low(r))
	{
		V1[++tot1]=rt[r];
	}
	int ans=qu(1,sz,k);
	printf("%d\n",ans);
}
int main()
{
	int m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)rt[i]=++cnt;
	for(int i=1;i<=n;i++)scanf("%d",a+i),S[++sz]=a[i];
	for(int i=1;i<=m;i++)
	{
		scanf("%s",Q[i].opt);
		if(Q[i].opt[0]=='C')
		{
			scanf("%d%d",&Q[i].ql,&Q[i].qr);
			S[++sz]=Q[i].qr;
		}
		else 
		{
			scanf("%d%d%d",&Q[i].ql,&Q[i].qr,&Q[i].k);
		}
	}
	sort(S+1,S+1+sz);
	sz=unique(S+1,S+1+sz)-S-1;
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(S+1,S+1+sz,a[i])-S;
		modify(i, a[i], 1);
	}
	for(int i=1;i<=m;i++)
	{
		if(Q[i].opt[0]=='C')
		{
			modify(Q[i].ql,a[Q[i].ql],-1);
			a[Q[i].ql]=lower_bound(S+1,S+1+sz,Q[i].qr)-S; 
			modify(Q[i].ql,a[Q[i].ql],1);
		}
		else if(Q[i].opt[0]=='Q')
		{
			_qu(Q[i].ql-1,Q[i].qr,Q[i].k);
		}
	}
 } 

 

你可能感兴趣的:(数据结构------树状数组,数据结构------线段树)