hdu6703 array权值线段树

题目链接、

 

因为1操作每次加一个1e7,而k在n以内,所以1操作一下相当于把a[pos]删掉了

答案一定在[1,n+1]内,然后建一颗权值线段树,存下标的最大值

每次2操作,相当于询问在[k,n+1]中,下标大于r的最小值是多少

查询先看左子树中是否在[k,n+1],左子树中最大下标是否大于r

如果左子树查询完毕没有查到结果,那么看右子树是否可以查询。

 

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7,inf = 0x3f3f3f3f;
int a[maxn],idx[maxn],n,m;
int Tree[maxn<<2];
void build(int l=1,int r=n+1,int x=1){
    Tree[x] = idx[l];
    if(l == r)return;
    int mid = l+r>>1;
    build(l,mid,x<<1),build(mid+1,r,x<<1|1);
    Tree[x] = max(Tree[x<<1],Tree[x<<1|1]);
}
void del(int pos,int l=1,int r=n+1,int x=1){
    if(l == r){
        Tree[x] = inf;
        return;
    }
    int mid = l+r>>1;
    if(pos<=mid)del(pos,l,mid,x<<1);
    else del(pos,mid+1,r,x<<1|1);
    Tree[x] = max(Tree[x<<1],Tree[x<<1|1]);
}
int query(int k,int R,int l=1,int r=n+1,int x=1){
    if(l == r)return l;
    int mid = l+r>>1,ans = -1;
    if(Tree[x<<1]>R && k<=mid)ans = query(k,R,l,mid,x<<1);
    if(~ans)return ans;
    if(Tree[x<<1|1]>R)return query(k,R,mid+1,r,x<<1|1);
    return -1;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),idx[a[i]] = i;
        idx[n+1] = n+1;
        a[n+1] = n+1;
        build();
        int ans = 0;
        while(m--){
            int opt,t1,t2;
            scanf("%d%d",&opt,&t1);
            t1 ^= ans;
            if(opt == 1){
                del(a[t1]);
            }else{
                scanf("%d",&t2);
                t2 ^= ans;
                ans = query(t2,t1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值