【NOIP2017】列队

题面

https://www.luogu.org/problem/P3960

题解

搬运一下去年的工作。

题解是$splay$,但是我傻逼写的$treap$。

对于$n=1$的情况,$treap$维护序列插入删除,对于$n$任意的情况,动态开点就可以了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<ctime>
#include<cstdlib>

using namespace std;

const long long INF=1e8;
const double eqs=1e-6;

struct node{
  node *ch[2],*fa;
  long long pri,s,l,siz;
  long long val;
} root[300500],r;

long long n,m,q,x,y,mv[300500],mrv,rank,rk2;

bool opt(node *x) {
  return (x->fa->ch[1]==x);
}

void rotate(node *x) {
  node *y=x->fa;
  bool o=opt(x);
  x->fa=y->fa; y->fa->ch[opt(y)]=x;
  y->fa=x; y->ch[o]=x->ch[1^o];
  if (x->ch[1^o]!=NULL) x->ch[1^o]->fa=y; x->ch[1^o]=y;
  y->siz=y->l;
  if (y->ch[0]!=NULL) y->siz+=y->ch[0]->siz;
  if (y->ch[1]!=NULL) y->siz+=y->ch[1]->siz;
  x->siz=x->l + y->siz;
  if (x->ch[o]!=NULL) x->siz+=x->ch[o]->siz;
}

void insert(node *now,long long v,long long s,long long l) {
  now->siz+=l;
  if (now->ch[v>now->val]==NULL) {
    node *xx=new node;
    now->ch[v>now->val]=xx;
    xx->val=v, xx->pri=rand()%INF, xx->s=s, xx->l=l , xx->siz=l , xx->fa=now;
    while (xx->pri > xx->fa->pri) rotate(xx);
    return;
  }
  else insert(now->ch[v>now->val],v,s,l);
}

void erase(node *now) {
  int le=now->l;
  now->l=0;
  node *it=now;
  while (it!=NULL) it->siz-=le,it=it->fa;
  int cnt;
  while (true) {
    cnt=0;
    if (now->ch[0]!=NULL) cnt++;
    if (now->ch[1]!=NULL) cnt++;
    if (cnt==0) {
      now->fa->ch[opt(now)]=NULL;
      //while (now!=NULL) now->siz-=len,now=now->fa;
      return;
    }
    else if (cnt==1) {
      if (now->ch[0]!=NULL) cnt=0; else cnt=1;
      now->fa->ch[opt(now)]=now->ch[cnt];
      now->ch[cnt]->fa=now->fa;
      //while (now!=NULL) now->siz-=len,now=now->fa;
      return;
    }
    else {
      if (now->ch[0]->pri > now->ch[1]->pri) cnt=0; else cnt=1;
      rotate(now->ch[cnt]);
    }
  }
}

long long fbrdd(node *now) {
  if (now==NULL) return -1;
  long long les;
  if (now->ch[0]!=NULL) les=now->ch[0]->siz; else les=0;
  if (rk2+les == x) {
    erase(now);
    return now->s;
  }
  else if (x<rk2+les) return fbrdd(now->ch[0]);
  else { rk2+=les+1; return fbrdd(now->ch[1]); }
}

void del(node *now,long long mi){
  //printf("ylq %lld
",mi);
  int le=now->l;
  now->l=0;
  node *it=now;
  while (it!=NULL) it->siz-=le,it=it->fa;

  int cnt;
  bool suc=false;
  now->val=-1;
  while (true) {
    //printf("DEBUG shx %lld
",mi);
    cnt=0;
    if (now->ch[0]!=NULL) cnt++;
    if (now->ch[1]!=NULL) cnt++;
    if (cnt==0 && !suc) {
      suc=true;
      if (mi-now->s) {
        //printf("DEBUG %lld %lld %lld
",now->s,le,mi);
        node *ch0=new(node);
        ch0->ch[0]=NULL,
        ch0->ch[1]=NULL,
        ch0->fa=now,
        ch0->pri=rand()%INF,
        ch0->s=now->s,
        ch0->l=mi-now->s,
        ch0->siz=mi-now->s;
        ch0->val=now->val;
        now->ch[0]=ch0;
        int len=ch0->siz; it=ch0;
        while (it->fa!=NULL) it=it->fa,it->siz+=len;
        while (ch0->pri > ch0->fa->pri) rotate(ch0);
      }
      if (now->s+le-1-mi) {
        //printf("DEBUG %lld %lld %lld
",now->s,le,mi);
        node *ch1=new(node);
        ch1->ch[0]=NULL,
        ch1->ch[1]=NULL,
        ch1->fa=now,
        ch1->pri=rand()%INF,
        ch1->s=mi+1,
        ch1->l=now->s+le-1-mi,
        ch1->siz=now->s+le-1-mi;
        ch1->val=now->val;
        now->ch[1]=ch1;
        int len=ch1->siz; it=ch1;
        while (it->fa!=NULL) it=it->fa,it->siz+=len;
        while (ch1->pri > ch1->fa->pri) rotate(ch1);
      }
    }
    else if (cnt==0 && suc) {
      now->fa->ch[opt(now)]=NULL;
      return;
    }         
    else if (cnt==1 && !suc) {
      if (now->ch[0]!=NULL) cnt=0; else cnt=1;
      rotate(now->ch[cnt]);
    }
    else if (cnt==1 && suc) {
      if (now->ch[0]!=NULL) cnt=0; else cnt=1;
      now->fa->ch[opt(now)]=now->ch[cnt];
      now->ch[cnt]->fa=now->fa;
      return;
    }
    else {
      if (now->ch[0]->pri > now->ch[1]->pri) cnt=0; else cnt=1;
      rotate(now->ch[cnt]);
    }
  }
}

void fbrd(node *now) {
  if (now==NULL) return;
  long long les;
  if (now->ch[0]!=NULL) les=now->ch[0]->siz; else les=0;
  if (rank+les <= y && y < rank+les+now->l) {
    long long mid=now->s+(y-rank-les);
    printf("%lld
",mid);
    del(now,mid);
    long long nxt=fbrdd(&r);
    insert(&root[x],++mv[x],nxt,1);
    insert(&r,++mrv,mid,1);
  }
  else if (y<rank+les) fbrd(now->ch[0]); else rank+=les+now->l,fbrd(now->ch[1]);
}

void dfs(node *now){
  if (now->ch[0]!=NULL) dfs(now->ch[0]);
  printf("DEBUG : %lld %lld
",now->s,now->l);
  if (now->ch[1]!=NULL) dfs(now->ch[1]);
}

int main(){
  long long i;
  scanf("%lld %lld %lld",&n,&m,&q);
  r.val=-INF,r.pri=INF,r.s=-1,r.siz=1,r.l=1;
  mrv=0;
  for (i=1;i<=n;i++) {
    root[i].val=-INF,root[i].pri=INF,root[i].s=-1,root[i].siz=1,root[i].l=1;
    insert(&root[i],++mv[i],(i-1)*m+1,m-1);
    insert(&r,++mrv,i*m,1);
  }
  for (i=1;i<=q;i++) {
    rank=rk2=0;
    scanf("%lld %lld",&x,&y);
    //dfs(&root[x]);
    if (y==m) {
      long long nxt=fbrdd(&r);
      printf("%lld
",nxt);
      insert(&r,++mrv,nxt,1);
    }
    else fbrd(&root[x]);
  }
  return 0;
}
原文地址:https://www.cnblogs.com/shxnb666/p/11423847.html