成都磨子桥技工学校 / 数据结构 Challenge 9

描述

给一个长为N的数列,有M次操作,每次操作是以下两种之一:

(1)删除某个位置的数

(2)求数列某位置的值

题解

一开始想的是平衡树,后来想了想没有骚操作,就只要记录该位置是否有效,删除就变成0,然后查询仿值域线段树查k小。

不晓得如果有插入行不行。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,cnt;
int a[maxn];
int root,ls[maxn<<1],rs[maxn<<1],sum[maxn<<1];

template<class T>inline void read(T &x){
  x=0;int f=0;char ch=getchar();
  while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  x= f ? -x : x ;
}

void update(int rt){
  sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}

void build(int &rt,int l,int r){
  rt=++cnt;
  if(l==r){
    sum[rt]=1;
    return ;
  }
  int mid=(l+r)>>1;
  build(ls[rt],l,mid);
  build(rs[rt],mid+1,r);
  update(rt);
}

void modify(int rt,int l,int r,int pos){
  if(l==r){
    sum[rt]=0;
    return;
  }
  int mid=(l+r)>>1;
  if(sum[ls[rt]]>=pos) modify(ls[rt],l,mid,pos);
  else modify(rs[rt],mid+1,r,pos-sum[ls[rt]]);
  update(rt);
}

int query(int rt,int l,int r,int pos){
  if(l==r) return a[l];
  int mid=(l+r)>>1;
  if(sum[ls[rt]]>=pos) return query(ls[rt],l,mid,pos);
  else return query(rs[rt],mid+1,r,pos-sum[ls[rt]]);
}

int main(){
  read(n);read(m);
  for(int i=1;i<=n;i++) read(a[i]);
  build(root,1,n);
  for(int i=1;i<=m;i++){
    char op[2];
    scanf("%s",op);
    if(op[0]=='D'){
      int pos;read(pos);
      modify(1,1,n,pos);
    }
    else {
      int pos;read(pos);
      printf("%d
",query(1,1,n,pos));
    }
  }
}
View Code
原文地址:https://www.cnblogs.com/sto324/p/11380090.html