zoukankan      html  css  js  c++  java
  • hdu 6730 线段树 2019-ccpc网络赛02

    hdu 6730 线段树 2019-ccpc网络赛02

    题意:

    数组a时一个1~n的全排列,有如下两种操作
    1 x,将a[x]+=1e7
    2 r,k 查询大于等于k的最小值但不在数组中前r项中
    (数组长度1e5,k<1e5)

    思路:

    首先观察可知在题目中查询的答案一定再1~n+1的范围内(因为k很小,操作一加的很大)
    那么其实1操作就是取消掉禁用。之后考虑正着做比较难,则反着做查询k~n+1中最小的没被禁用的。
    这里用一颗线段树就表示num[i]是否被禁用,查询的时候查询k~n+1中最小的没被ban掉的就好了,这里左右子树选择的时候再判断一下左子树上k~mid的最值就好。左右判断一个log,查询本身一个log。最终nlogn^2通过此题.

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    #define pii pair<int,int>
    #define PB push_back
    #define X first
    #define Y second
    using namespace std;
    int t,n,m,x;
    const int maxn = 5e5;
    const int inf = 0x3f3f3f3f;
    int a[maxn],b[maxn];
    int rmin[maxn];
    int ans,op,pos,minx,k,r;
    void init(){
        memset(rmin,0,sizeof(rmin));
    }
    void update(int x,int y,int L,int R,int rt){
        if(L==R){
            rmin[rt]=y;
            return;
        }
        int mid = (L+R)/2;
        if(x<=mid) update(x,y,L,mid,rt*2);
        else update(x,y,mid+1,R,rt*2+1);
        rmin[rt]=max(rmin[rt*2],rmin[rt*2+1]);
    }
    int get_min(int L,int R,int l,int r,int rt){
        if(L>=l&&R<=r) return rmin[rt];
        if(r<L||l>R) return 0;
        int mid = (L+R)/2;
        return max(get_min(L,mid,l,r,rt*2),get_min(mid+1,R,l,r,rt*2+1));
    }
    void query(int L,int R,int r,int k,int rt){
        if(L==R){
            ans = L;
            return;
        }
        int mid = (L+R)/2;
        if(k<=mid&&rmin[rt*2]>r&&get_min(L,mid,k,mid,rt*2)>r) query(L,mid,r,k,rt*2);
        else query(mid+1,R,r,k,rt*2+1);
    }
    int main(){
        //cin>>t;
        scanf("%d",&t);
        while(t--){
            //cin>>n>>m;
            scanf("%d%d",&n,&m);
            init();
            ans=0;
            for(int i=1;i<=n;i++){
                //cin>>x;
                scanf("%d",&x);
                a[x]=i;
                b[i]=x;
                update(x,i,1,n+1,1);
            }
            update(n+1,inf,1,n+1,1);
            for(int i=0;i<m;i++){
                scanf("%d",&op);
                //cin>>op;
                if(op==1){
                    scanf("%d",&pos);
                    //cin>>pos;
                    pos^=ans;
                    update(b[pos],inf,1,n+1,1);
                }
                else{
                    scanf("%d%d",&r,&k);
                    //cin>>r>>k;
                    r^=ans;k^=ans;
                    //cout<<"r:"<<r<<" k:"<<k<<endl;
                    ans = minx = inf;
                    query(1,n+1,r,k,1);
                    printf("%d
    ",ans);
                    //cout<<ans<<endl;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    CAF(C++ Actor Framework)介绍
    Android C++打印函数调用栈
    80%应聘者都不及格的JS面试题
    二叉树的最近公共祖先--递归解法
    mysql的InnoDB引擎的行记录格式ROW_FORMAT
    Docker安装mysql 集群(pxc方式)及负载均衡实践
    主机ping不通虚拟机,虚拟机可以ping通主机解决方式
    springboot源码解析
    springmvc源码解析
    寻找两个正序数组的中位数
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/11432003.html
Copyright © 2011-2022 走看看