2019CCPC网络赛 1002 HDU 6703(权值线段树)

2019CCPC网络赛 1002 HDU 6703(权值线段树)

思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中顺序)在原序列中对应的值,1操作就是对应值变成inf(即一定大于k),特判k>n,输出k+1,若未找到,则输出n+1。

#include<bits/stdc++.h>
#define rep(i,a,b)	for(int i=a;i<=b;i++)
#define mid (l+r)/2
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll inf=1e10;
ll dat[4*maxn],num[maxn],b[maxn],id[4*maxn];
void build(int a,int l,int r){
	if(l==r)	dat[a]=num[l];
	else{
		build(a<<1,l,mid);
		build(a<<1|1,mid+1,r);
		dat[a]=max(dat[a<<1],dat[a<<1|1]);
	}
}
void update(int a,int l,int r,int p){
	if(l==r){
		dat[a]=inf;
		return;
	}
	if(p<=mid)	update(a<<1,l,mid,p);
	else		update(a<<1|1,mid+1,r,p);
	dat[a]=max(dat[a<<1],dat[a<<1|1]);		
}
int query(int a,int l,int r,int s,int t,int k){
	if(l==r){
		if(dat[a]>k)	return	b[id[a]];
		else	return -1;
	}
	int k1=-1,k2=-1;
	if(s<=mid && dat[a<<1]>k)	k1=query(a<<1,l,mid,s,t,k);
	if(k1!=-1)	return k1;
	if(t>mid  && dat[a<<1|1]>k)	k2=query(a<<1|1,mid+1,r,s,t,k);
	return k2;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(dat,0,sizeof(dat));
		int n,m,ans=0;
		scanf("%d%d",&n,&m);
		rep(i,1,n)	scanf("%lld",&b[i]),num[b[i]]=i;
		build(1,1,n);
		memcpy(id,dat,sizeof(dat));
		rep(i,1,m){
			int t,l,r;
			scanf("%d%d",&t,&l);
			l^=ans;
			if(t==1){
				//cout<<l<<endl; 
				update(1,1,n,b[l]);
			}
			else{
				scanf("%d",&r);
				r^=ans;
				if(r>n){
					printf("%d",r+1);
					continue;
				}
				ans=query(1,1,n,r,n,l);
				if(ans==-1)	ans=n+1;
				printf("%d\n",ans);
			}
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值