zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    一生不可错过的五句话
    分布式缓存系统Memcached简介与实践[转]
    telnet serverip serverport 可以测试服务器端口是否通
    使用c#生成高品质小空间的缩略图
    sql server2005对tsql的增强之在聚合函数的后面使用over关键字
    (转)让你受益终身的10个Word实用技巧
    sql取所有记录中每天的最后一笔交易的记录
    屏蔽服务器端包含在文件不存在时报错的错误信息
    c#农历日历类
    Niubility 英语教程
  • 原文地址:https://www.cnblogs.com/PdrEam/p/15526552.html
Copyright © 2011-2022 走看看