hdu 6703 array

给定序列,互不相同的全排列 n1e5内的。

1操作使得某个点+1e7

2操作 找一个要求【不等于a1...ar 中的值】【且这个值大于等于k】【值最小】

主席树+set

暴力的想,从小到大取数看看可不可行。又由于整个序列是全排序。

那么不在[1,r]中,就相当于在[r+1,n]中找一个大于等于k。这个可以用主席树写。

然后考虑操作1,这个点+1e7之后这个点原先的值就不会被[1,r]这个限制范围了

比如[4 2 1] 3 5 6 ,先对4这个位置+1e7 然后k=4

对4 +1e7之后,我们发现4就可用了。原先是 4 2 1不可用。现在变成了 4+1e7 2 1不可用。

把操作1之后的数丢进set里。

然后发现不冲突,那么就可以取小得到答案了。

#include<bits/stdc++.h>
#define inf 1e18
#define ll long long 
#define ull unsigned long long 
#define int long long
#define PI acos(-1.0)
#define PII pair<int,int>
using namespace std;
const int N = 1e5+7;
const int p = 998244353;
int m,n,idx,a[N],root[N];
set<int>s;
struct node{
    int l,r,cnt;
}tr[N << 5];
void build(int l,int r,int &rt){
    rt=++idx;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,tr[rt].l);build(mid+1,r,tr[rt].r);
}
int insert(int p,int l,int r,int x){
    int q = ++idx;
    tr[q]=tr[p];tr[q].cnt++;
    if(l==r)    return q;
    int mid = l+r >>1;
    if(x<=mid)    tr[q].l=insert(tr[p].l,l,mid,x);
    else        tr[q].r=insert(tr[p].r,mid+1,r,x);
    return  q;
}
int query(int q,int p,int l,int r,int k){
    if(l==r)    return l;
    int mid =l+r>>1;
    int x1 = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
    int x2 = tr[tr[q].r].cnt - tr[tr[p].r].cnt;
    int ans = inf;
    if(k<=mid&&x1)    ans = query(tr[q].l,tr[p].l,l,mid,k);
    if(ans != inf)    return ans;
    if(x2)    ans = query(tr[q].r,tr[p].r,mid+1,r,k);
    return ans;
}
void solve(){
    s.clear();
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
    idx = 0; build(1,n+1,root[0]);
    for(int i=1;i<=n;++i)root[i]=insert(root[i-1],1,n+1,a[i]);
    root[n+1] = insert(root[n],1,n+1,n+1);
    int ans = 0;
    while(m--){
        int op;int t1,t2,t3;scanf("%lld",&op);
        if(op==1){
            scanf("%lld",&t1);
            int pos = ans ^ t1;
            s.insert(a[pos]);
        }
        else{
            scanf("%lld%lld",&t2,&t3);
            int r = t2 ^ ans,k = t3 ^ ans;
            //printf("r %lld k %lld
",r,k);
            //[r+1,n+1]找大于等于k的值
            ans = query(root[n+1],root[r],1,n+1,k);
            if(s.size()){
                auto it = s.lower_bound(k);
                if(it!=s.end()) ans = min(ans,*it);
            } 
            printf("%lld
",ans);
        }
    }
}
signed main(){
    int t=1;
       scanf("%lld",&t);
    for(int _=1;_<=t;++_){
        solve();
    }
    return 0;
}

 权值线段树

【不等于a1...ar 中的值】 == 【值下标大于r】

【且这个值大于等于k】 == 【查询时在[k,n+1]中查询】

【最小】 == 【能左子树就左,查询时有交集取小】

#include<bits/stdc++.h>
#define inf 1e7
#define ll long long 
#define ull unsigned long long 
#define PI acos(-1.0)
#define PII pair<int,int>
using namespace std;
const int N = 1e5+7;
const int p = 998244353;
int n,q;
struct node{
    int l,r,pos;   //维护区间下标最大值
}t[4*N];
int a[N];
void build(int l,int r,int o){
    t[o].l=l;
    t[o].r=r;
    if(l==r)    return ;
    int mid=(l+r)>>1;
    build(l,mid,o<<1);
    build(mid+1,r,o<<1|1);
}
void pushup(int o){
    t[o].pos=max(t[o<<1].pos,t[o<<1|1].pos);
}
void add(int o,int x,int pos){   //添加操作 维护区间下标最大值
    if(t[o].l==t[o].r&&t[o].l==x){
        t[o].pos=pos;
        return ;
    }
    int mid=(t[o].l+t[o].r)>>1;
    if(x<=mid)    add(o<<1,x,pos);
    else        add(o<<1|1,x,pos);
    pushup(o);
}
int query(int o,int l,int r,int ask){
    if(t[o].l==t[o].r){      //到叶子节点
        if(t[o].pos>ask)    return t[o].l;
        else   return inf;
    }
    if(t[o].l==l&&t[o].r==r){//剪枝 
        if(t[o<<1].pos>ask)    return query(o<<1,l,(l+r)>>1,ask);
        else if(t[o<<1|1].pos>ask)    return query(o<<1|1,(l+r)>>1|1,r,ask);
        else   return inf;
    }
    int mid=(t[o].l+t[o].r)>>1; 
    if(r<=mid)    return query(o<<1,l,r,ask);     
    else if(l>mid)    return query(o<<1|1,l,r,ask);   
    else   return min(query(o<<1,l,mid,ask),qurey(o<<1|1,mid+1,r,ask));   
}     
void solve(){
    memset(t,0,sizeof t);
    scanf("%d%d",&n,&q);
    build(1,1+n,1);
    for(int i=1; i<=n; i++){
        scanf("%d",&a[i]);
        add(1,a[i],i);
    }
    add(1,n+1,inf);
    int op,last=0;
    while(q--){
        scanf("%d",&op);
        if(op==1){
            int pos;scanf("%d",&pos);
            pos^=last;add(1,a[pos],inf);
        }
        else{
            int r,k;scanf("%d%d",&r,&k);
            r^=last,k^=last;last=query(1,k,n+1,r);
            printf("%d
",last);
        }
    }
}
signed main(){
    int t=1;
       scanf("%lld",&t);
    for(int _=1;_<=t;++_){
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/PdrEam/p/15526552.html