C72 线段树分裂合并+集合维护 P2824 [HEOI2016/TJOI2016] 排序

视频链接:258 线段树分裂合并+集合维护 P2824 [HEOI2016TJOI2016] 排序_哔哩哔哩_bilibili

 

 

Luogu P2824 [HEOI2016/TJOI2016] 排序

【总结】C++ 基础数据结构 —— STL之集合(set)用法详解_c++ stl set-CSDN博客

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;

void read(int &x){ //快读
  x=0; char c=getchar();
  while(!isdigit(c))c=getchar();
  while(isdigit(c))x=x*10+c-'0',c=getchar();
}
const int N=100005;
#define mid ((l+r)>>1)
typedef set<int>::iterator it; //set定位器
set<int> st;
int n,m,tot,root[N],o[N];
int ls[N*55],rs[N*55],sum[N*55];
//o[p]:记录p位置之后的一段是升序还是降序
//sum[x]:记录区间权值个数之和

void change(int &x,int l,int r,int p){ //点修
  x=++tot; sum[x]=1;
  if(l==r) return;
  if(p<=mid)change(ls[x],l,mid,p);
  else change(rs[x],mid+1,r,p);
}
int query(int x,int l,int r){ //点查
  if(l==r) return l;
  if(ls[x]) return query(ls[x],l,mid);
  else return query(rs[x],mid+1,r);
}
void merge(int &x,int y){ //合并
  if(!x||!y){x+=y;return;}
  sum[x]+=sum[y];
  merge(ls[x],ls[y]);
  merge(rs[x],rs[y]);
}
void split(int x,int &y,int k,int o){ //分裂
  //将x从k处斩断,一段归x,另一段归y
  if(sum[x]==k) return;
  y=++tot; sum[y]=sum[x]-k; sum[x]=k;
  if(o==0){ //升序,前k小归x
    if(k<=sum[ls[x]]) split(ls[x],ls[y],k,o),swap(rs[x],rs[y]);
    else split(rs[x],rs[y],k-sum[ls[x]],o);
  }
  else{     //降序,后k大归x
    if(k<=sum[rs[x]]) split(rs[x],rs[y],k,o),swap(ls[x],ls[y]);
    else split(ls[x],ls[y],k-sum[rs[x]],o);
  }
}
it SPL(int p){ //从p处分裂
  it i=st.lower_bound(p); //p在集合中的位置
  if(*i==p) return i;
  else i--; //i-1即p所在线段树的版本
  split(root[*i],root[p],p-*i,o[p]=o[*i]);
  return st.insert(p).first; //集合插入p并返回其位置
}
int main(){
  read(n),read(m); int x,op,l,r,q;
  for(int i=1;i<=n;++i){
    read(x),change(root[i],1,n,x); //n颗线段树
    st.insert(i); //下标插入集合
  }
  while(m--){
    read(op),read(l),read(r);
    it a=SPL(l), b=SPL(r+1); //分裂成4段
    for(it i=++a;i!=b;++i)
      merge(root[l],root[*i]); //合并中间段
    o[l]=op; //记录l位置之后的一段是升序还是降序
    st.erase(a,b); //删除集合[l+1,r]段
  }
  read(q); SPL(q); SPL(q+1); //把q线段树变成链
  printf("%d\n",query(root[q],1,n));
}

 

posted @ 2023-11-24 18:28  董晓  阅读(139)  评论(0编辑  收藏  举报