hdu.6703 array

h d u . 6703   a r r a y hdu.6703\ array hdu.6703 array

思路:线段树。

对操作2分析可知: a n s ∈ [ 1 , n + 1 ] ans\in[1,n+1] ans[1,n+1]

操作1相当于:将一个数变得很大就可以直接将 a [ p o s ] a[pos] a[pos]的下标置为 n + 1 n+1 n+1,因为此时 a [ p o s ] a[pos] a[pos]的值肯定满足大于等于 k k k,而且原来的 a [ p o s ] ≥ r a[pos]\ge r a[pos]r就肯定能被取到。

因此考虑建立权值线段树储存值,然后用一个数组维护一个区间的最大下标 m x [ x ] mx[x] mx[x]

区间查询 查找最大下标大于 r r r,且值大于等于 k k k的最小值。

每次单点更新就将 m x [ x ] = n + 1 mx[x]=n+1 mx[x]=n+1

#include
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define pb push_back
#define il inline
int id[N],t,n,m,a[N];
struct SegTree{
     
    int mx[N<<2];
    void re(int x){
     
        mx[x]=max(mx[lx],mx[rx]);
    }
    void build(int x,int l,int r){
     
        //printf("x=%d,(%d,%d)\n",x,l,r);
        if(l==r){
     
            mx[x]=id[l];return;
        }
        int mid=l+r>>1;
        build(lx,l,mid);
        build(rx,mid+1,r);
        re(x);
    }
    void upd(int x,int l,int r,int val){
     
        if(l==r){
     
            mx[x]=n+1;
            return;
        }
        int mid=l+r>>1;
        if(val<=mid) upd(lx,l,mid,val);
        else upd(rx,mid+1,r,val);
        re(x); 
    }
    int query(int x,int l,int r,int R,int K){
     
        if(r<K) return -1;
        if(l==r) return l;
        int ans=-1,mid=l+r>>1;
        if(mx[lx]>R) ans=query(lx,l,mid,R,K);
         if(ans==-1&&mx[rx]>R) ans=query(rx,mid+1,r,R,K);
        return ans;
     }
}T; 
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]);
            id[a[i]]=i;
        }
        id[n+1]=n+1;
        T.build(1,1,n+1);
        int lst=0;
        while(m--){
     
            int op,x,y;
            scanf("%d",&op);
            if(op==1){
     
                scanf("%d",&x),x^=lst;
                T.upd(1,1,n+1,a[x]);
            }
            else {
     
                scanf("%d%d",&x,&y);
                x^=lst,y^=lst;
                lst=T.query(1,1,n+1,x,y);
                printf("%d\n",lst);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(线段树)