权值线段树

array

题意

给出一个1,n的排列,有q(q<=1e5)有以下两个操作(强制在线):
1.给位置pos上的数+1e7
2.询问[1,r]区间上大于等于k(1e5)的数最小是多少(这个数不能等于[1,r]区间中的任意一个数)

分析

由数据我们可以知道只要对一个数进行了操作1,相当于把这个数挖掉了,所以我们想要找到最小的满足题意的值,只需要维护区间最大值,只要区间中有值大于等于k,就可以进区间找,但是这样会带来很多问题,首先是区间全是连续的无法插,其次是可以插,如何找到这个空?这个时候需要转化思维,既然普通线段树难以维护,是否考虑主席树or权值线段树,使用权值线段树,维护区间最大的标号,如果标号大于等于r,先往左边找,但是这样可能会导致[1,mid]中有标号比r大的,但是比k小,这样就会一直找到mid,只需要开一个变量记一下,如果[1,mid]不合法继续到右子树找就行了(比赛的时候心态崩了这么简单处理都不会了,要是冷静下来改改就过了)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+4;
const int inf=0x3f3f3f3f;
int tr[maxn<<2];
int a[maxn],b[maxn],vis[maxn];
void build(int o,int l,int r){
	if(l==r)tr[o]=b[l];
	else {
		int mid=l+r>>1;
		build(o<<1,l,mid);
		build(o<<1|1,mid+1,r);
		tr[o]=max(tr[o<<1],tr[o<<1|1]);
	}
}
void update(int o,int l,int r,int p){
	if(l==r)tr[o]=inf-1;
	else {
		int mid=l+r>>1;
		if(p<=mid)update(o<<1,l,mid,p);
		else update(o<<1|1,mid+1,r,p);
		tr[o]=max(tr[o<<1],tr[o<<1|1]);
	}
}

int ok=0;
int query(int o,int l,int r,int x,int y,int k){
	//cout<<l<<" "<<r<<endl;
		if(l==r){
			//cout<<tr[o]<<endl;
			if(tr[o]<=y){
				return inf;
			}
			ok=1;
			return l;			
		}
		else {
			int mid=l+r>>1;
			int ans=inf;
			if(k<=mid&&tr[o<<1]>y){
				
				  ans=query(o<<1,l,mid,x,y,k);
				  if(ans!=inf)return ans;
				  else if(ok==0){
					  return query(o<<1|1,mid+1,r,x,y,k);
				  }
			}
			else {
				return query(o<<1|1,mid+1,r,x,y,k);
			}
		}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,q;
		scanf("%d%d",&n,&q);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		int sz=n+2;
		for(int i=1;i<=n+2;i++){
			b[i]=inf-1;
		}
		for(int i=1;i<=n;i++)vis[i]=0;
		for(int i=1;i<=n;i++)b[a[i]]=i;
		build(1,1,sz);
		int pos,r,k;
		int ans=0;
		while(q--){
			int op;
			ok=0;
			scanf("%d",&op);
			if(op==1){
				scanf("%d",&pos);
				pos=pos^ans;
				if(vis[pos]==0)update(1,1,sz,a[pos]),vis[pos]=1;
			}
			else {
				scanf("%d%d",&r,&k);
				r=r^ans;
				k=k^ans;
				 ans=query(1,1,sz,1,r,k);
				printf("%d
",ans);
			}
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/ttttttttrx/p/11406186.html