[spaly模拟 线段树] BZOJ 4825 [Hnoi2017]单旋

发现旋最小值到根 最小值深度变为1 他的右子树深度不变 其他都加1
旋最大值类似 这个只要线段树就好了 怎么求子树 看他的father
插入操作 找出前驱和后继 一定是祖先子孙关系 新点往深度大的下面挂

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005;

int sx[N],icnt;
inline int Bin(int x){
  return lower_bound(sx+1,sx+icnt+1,x)-sx;
}

int T[N<<2];
inline void Add(int x,int l,int r,int ql,int qr,int t){
  if (ql>qr) return;
  if (ql<=l && r<=qr)
    return void(T[x]+=t);
  if (T[x]) T[x<<1]+=T[x],T[x<<1|1]+=T[x],T[x]=0;
  int mid=(l+r)>>1;
  if (ql<=mid) Add(x<<1,l,mid,ql,qr,t);
  if (qr>mid) Add(x<<1|1,mid+1,r,ql,qr,t);
}
inline void Modify(int x,int l,int r,int t,int a){
  if (l==r)
    return void(T[x]=a);
  if (T[x]) T[x<<1]+=T[x],T[x<<1|1]+=T[x],T[x]=0;
  int mid=(l+r)>>1;
  if (t<=mid) Modify(x<<1,l,mid,t,a);
  else Modify(x<<1|1,mid+1,r,t,a);
}
inline int Query(int x,int l,int r,int t){
  if (l==r)
    return T[x];
  if (T[x]) T[x<<1]+=T[x],T[x<<1|1]+=T[x],T[x]=0;
  int mid=(l+r)>>1;
  if (t<=mid) return Query(x<<1,l,mid,t);
  else return Query(x<<1|1,mid+1,r,t);
}

int m;
int ord[N],x[N];
set<int> Set;
typedef set<int>::iterator IT;
int fat[N],ch[N][2];

inline int D(int x){
  return Query(1,1,icnt,x);
}

inline void setc(int x,int y,int d){
  int dep=D(x); ch[x][d]=y;
  Modify(1,1,icnt,y,dep+1);
  fat[y]=x; Set.insert(y);
  printf("%d\n",dep+1);
}

int main(){
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(m);
  for (int i=1;i<=m;i++){
    read(ord[i]); if (ord[i]==1) read(x[i]),sx[++icnt]=x[i];
  }
  sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1;
  for (int i=1;i<=m;i++) if (ord[i]==1) x[i]=Bin(x[i]);
  int rt;
  for (int i=1;i<=m;i++)
    if (ord[i]==1){
      if (Set.empty())
    Modify(1,1,icnt,x[i],1),Set.insert(x[i]),fat[x[i]]=0,rt=x[i],printf("1\n");
      else{
    IT nxt=Set.lower_bound(x[i]);
    if (nxt==Set.begin())
      setc(*nxt,x[i],0);
    else{
      IT pre; pre=nxt;
      pre--;
      if (nxt==Set.end() || D(*pre)>D(*nxt))
        setc(*pre,x[i],1);
      else
        setc(*nxt,x[i],0);
    }
      }
    }else if (ord[i]==2){
      IT it=Set.begin();
      int x=*it,d=D(x);
      printf("%d\n",d);
      if (d==1) continue;
      Add(1,1,icnt,1,x-1,1);
      Add(1,1,icnt,fat[x],icnt,1);
      Modify(1,1,icnt,x,1);
      int rc=ch[x][1],p=fat[x];
      fat[x]=0;
      ch[p][0]=rc; if (rc) fat[rc]=p;
      ch[x][1]=rt; fat[rt]=x; rt=x;
    }else if (ord[i]==3){
      IT it=Set.end(); it--;
      int x=*it,d=D(x);
      printf("%d\n",d);
      if (d==1) continue;
      Add(1,1,icnt,1,fat[x],1);
      Add(1,1,icnt,x+1,icnt,1);
      Modify(1,1,icnt,x,1);
      int lc=ch[x][0],p=fat[x];
      fat[x]=0;
      ch[p][1]=lc; if (lc) fat[lc]=p;
      ch[x][0]=rt; fat[rt]=x; rt=x;
    }else if (ord[i]==4){
      IT it=Set.begin();
      int x=*it,d=D(x);
      Set.erase(x);
      printf("%d\n",d);
      if (d==1) {
    rt=ch[x][1]; fat[rt]=0;
    Add(1,1,icnt,1,icnt,-1);
    continue;
      }
      Add(1,1,icnt,x+1,fat[x]-1,-1);
      int rc=ch[x][1],p=fat[x];
      fat[x]=0;
      ch[p][0]=rc; if (rc) fat[rc]=p;
    }else{
      IT it=Set.end(); it--;
      int x=*it,d=D(x);
      Set.erase(x);
      printf("%d\n",d);
      if (d==1) {
    rt=ch[x][0]; fat[rt]=0; 
    Add(1,1,icnt,1,icnt,-1);
    continue;
      }
      Add(1,1,icnt,fat[x]+1,x-1,-1);
      int lc=ch[x][0],p=fat[x];
      fat[x]=0;
      ch[p][1]=lc; if (lc) fat[lc]=p;
    }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值