线段树 离散区间,单点维护区间

  这道题当时用线段树搞不行,用主席树搞,也不行。当场自闭。。。

  其实当时想到离散,但是没想到用单点维护线段树的区间。。。。。。

  你这样想,无非就是2e6次询问,最多1-e9被分成最多2e6区间,我们要求的位置,一定在这2e6点的右边第一个。

  那么把这个点,以及这个点x以及x+1的点保存下来。

  维护的时候,线段树初始化所有的单点值为1,并维护区间和,代表单点没有被删掉。

  我们优先往左查询,并保证不越过区间之外,如果查询到满足条件的,我们不再往后继续查询,否则往右查询。

  

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<bits/stdc++.h>
#define LL long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxx = 2e6+6;
struct node{
  int l,r;
  int cnt;
}tree[maxx<<2];
int op[maxx],pos[maxx];
vector<int>p;
int cnt,ans;
int get_pos(int x){
    return lower_bound(p.begin(),p.end(),x)-p.begin()+1;
}
void buildtree(int rt,int l,int r){
    tree[rt].l=l;
    tree[rt].r=r;
    if (l==r){
        tree[rt].cnt=r-l+1;
        return ;
    }
    int mid=(l+r)>>1;
    buildtree(lson,l,mid);
    buildtree(rson,mid+1,r);
    tree[rt].cnt=tree[lson].cnt+tree[rson].cnt;
}
void update(int rt,int pos){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if (l==r){
        tree[rt].cnt=0;
        return ;
    }
    int mid=(l+r)>>1;
    if (pos<=mid){
        update(lson,pos);
    }else{
        update(rson,pos);
    }
    tree[rt].cnt=tree[lson].cnt+tree[rson].cnt;
}
int flag=0;
void query(int rt,int ql,int qr){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if(l==r){
        if(tree[rt].cnt){
         //   cout<<l<<" "<<r<<endl;
            flag=1;
            ans=p[l-1];
        }
        return ;
    }
    int mid=(l+r)>>1;
    if (!flag && ql<=mid && tree[lson].cnt){
        ///如果当前没有查到,并且左儿子的区间和询问区间有交集,并且左儿子区间有没有被消除的点
        ///这里注意,左区间和不为0不代表一定有,因为我们不知道左区间和询问区间的交集是否有
        query(lson,ql,qr);
    }
    if (!flag && tree[rson].cnt){
        query(rson,ql,qr);
    }
}
int main(){
   int n,q;
   while(~scanf("%d%d",&n,&q)){
      cnt=0;
      for(int i=1;i<=q;i++){
         scanf("%d%d",&op[i],&pos[i]);
         p.push_back(pos[i]);
         p.push_back(pos[i]+1);
      }
      sort(p.begin(),p.end());
      p.erase(unique(p.begin(),p.end()),p.end());
      int sz=p.size();
      buildtree(1,1,sz);
      for (int i=1;i<=q;i++){
          if (op[i]==1){
             update(1,get_pos(pos[i]));
          }else{
             flag=0;
             query(1,get_pos(pos[i]),sz);
             printf("%d\n",ans);
          }
      }
   }
   return 0;
}

猜你喜欢

转载自www.cnblogs.com/bluefly-hrbust/p/11508332.html