zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    第8章 对象的容纳
    第 4 章 初始化和清除
    第 3 章 控制程序流程
    maven教程
    使用Eclipse构建Maven项目 (step-by-step)
    将 Maven生成的java项目转化为支持 Eclipse IDE的项目
    eclipse 中修改 M2_REPO的值
    FilenameUtils工具类
    导出excel小结(C#,.NET,Wpf)
    NPOI导出Excel表功能实现(多个工作簿)(备用)
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11423847.html
Copyright © 2011-2022 走看看