BZOJ 2028 [SHOI2009]会场预约

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2028

题解

splay,貌似有更简单的算法?

开两个splay,一个记所有开始时间,一个记所有结束时间。由于一个时间为[s,t][s,t]的会议需要冲掉所有满足:结束时间s\geq s并且开始时间t\leq t,因此这些会议必定是连续的,求出结束时间恰好s\geq s和开始时间恰好t\leq t的两个位置,splay区间删除这些位置即可。

代码

#include <cstdio>

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

const int maxn=200000;
const int inf=0x3f3f3f3f;

struct node
{
  node *son[2],*fa;
  int val,size;
};

struct splay_tree
{
  node tnode[maxn+10],*root;
  int cnt;

  int updata(node *x)
  {
    x->size=1;
    if(x->son[0]!=NULL)
      {
        x->size+=x->son[0]->size;
      }
    if(x->son[1]!=NULL)
      {
        x->size+=x->son[1]->size;
      }
    return 0;
  }

  int t(node *x)
  {
    return x->fa->son[1]==x;
  }

  int rotate(node *x)
  {
    node *f=x->fa;
    int k=t(x);
    x->fa=f->fa;
    if(f->fa!=NULL)
      {
        f->fa->son[t(f)]=x;
      }
    if(x->son[!k]!=NULL)
      {
        x->son[!k]->fa=f;
      }
    f->son[k]=x->son[!k];
    f->fa=x;
    x->son[!k]=f;
    updata(f);
    updata(x);
    return 0;
  }

  int splay(node *x,node *y)
  {
    while(x->fa!=y)
      {
        node *f=x->fa;
        if(f->fa==y)
          {
            rotate(x);
          }
        else if(t(x)==t(f))
          {
            rotate(f);
            rotate(x);
          }
        else
          {
            rotate(x);
            rotate(x);
          }
      }
    if(y==NULL)
      {
        root=x;
      }
    return 0;
  }

  node* newnode(int val)
  {
    node *x=&tnode[++cnt];
    x->son[0]=x->son[1]=x->fa=NULL;
    x->size=1;
    x->val=val;
    return x;
  }

  int insert(node *x,node *y)
  {
    if(x==NULL)
      {
        root=y;
        return 0;
      }
    if(y->val<x->val)
      {
        if(x->son[0]==NULL)
          {
            x->son[0]=y;
            y->fa=x;
          }
        else
          {
            insert(x->son[0],y);
          }
      }
    else
      {
        if(x->son[1]==NULL)
          {
            x->son[1]=y;
            y->fa=x;
          }
        else
          {
            insert(x->son[1],y);
          }
      }
    updata(x);
    return 0;
  }

  int clear()
  {
    cnt=0;
    insert(NULL,newnode(-inf));
    insert(root,newnode(inf));
    return 0;
  }

  int remove(node *x,node *y)
  {
    splay(x,NULL);
    splay(y,x);
    if(y->son[0]==NULL)
      {
        return 0;
      }
    int ans=y->son[0]->size;
    y->son[0]=NULL;
    return ans;
  }

  int getrank(node *x)
  {
    splay(x,NULL);
    if(x->son[0]==NULL)
      {
        return 1;
      }
    return x->son[0]->size+1;
  }

  node* getlow(node *x,int val)
  {
    if(val<=x->val)
      {
        if(x->son[0]==NULL)
          {
            return NULL;
          }
        return getlow(x->son[0],val);
      }
    else
      {
        if(x->son[1]==NULL)
          {
            return x;
          }
        node *y=getlow(x->son[1],val);
        if(y==NULL)
          {
            return x;
          }
        return y;
      }
  }

  node* getkth(node *x,int k)
  {
    int sz=1;
    if(x->son[0]!=NULL)
      {
        sz+=x->son[0]->size;
      }
    if(sz==k)
      {
        return x;
      }
    else if(sz>k)
      {
        return getkth(x->son[0],k);
      }
    else
      {
        return getkth(x->son[1],k-sz);
      }
  }
};

splay_tree st,ed;
int n;
char s[10];

int main()
{
  n=read();
  st.clear();
  ed.clear();
  for(int i=1; i<=n; ++i)
    {
      scanf("%s",s);
      if(s[0]=='A')
        {
          int x=read(),y=read();
          node *ednd=ed.getlow(ed.root,x),*stnd=st.getlow(st.root,-y);
          int tot=st.root->size;
          int ans=st.remove(stnd,st.getkth(st.root,tot-ed.getrank(ednd)+1));
          ed.remove(ednd,ed.getkth(ed.root,tot-st.getrank(stnd)+1));
          printf("%d\n",ans);
          st.insert(st.root,st.newnode(-x));
          ed.insert(ed.root,ed.newnode(y));
        }
      else
        {
          printf("%d\n",st.root->size-2);
        }
    }
  return 0;
}

发布了304 篇原创文章 · 获赞 69 · 访问量 6万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览