首页 > 代码库 > 【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树

【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树

这个题就是动态偏序对,每次操作做两个删除两个插入就好了。

#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 100010
using namespace std;
typedef long long LL;
typedef double D;
const D a=0.756;
LL ans;
struct ScapeGoat_Tree
{
    ScapeGoat_Tree *ch[2];
    int key,size,cover,ex;
    bool bad()
    {
      return cover*a+5<ch[0]->cover||cover*a+5<ch[1]->cover;
    }
    void pushup()
    {
       size=ch[0]->size+ch[1]->size+ex;
       cover=ch[0]->cover+ch[1]->cover+1;
    }
}*null,*stack[(MAXN<<5)+5],pool[(MAXN<<5)+5],*lst[(MAXN<<4)+5];
int  top,len;
inline void Init()
{
    null=pool;
    null->ch[1]=null->ch[0]=null;
    null->key=null->size=null->cover=null->ex=0;
    for(int  i=1;i<(MAXN<<5);i++)stack[++top]=pool+i;
}
inline ScapeGoat_Tree *New(int  key)
{
    ScapeGoat_Tree *p=stack[top--];
    p->ch[1]=p->ch[0]=null;
    p->key=key;
    p->size=p->ex=p->cover=1;
    return p;
}
struct Tree
{
    Tree *ch[2];
    int  mid,l,r;
    ScapeGoat_Tree *root;
    Tree(){ch[1]=ch[0]=NULL;mid=l=r=0;root=null;}
    void* operator new(size_t size);
}*root,*C,*mempool;
void* Tree :: operator new(size_t size)
{
    if(C==mempool)
    {
       C=new Tree[(1<<15)+5];
       mempool=C+(1<<15)+5;
    }
    C->root=null; 
    return C++;
}
void travel(ScapeGoat_Tree *p)
{
    if(p==null)return;
    travel(p->ch[0]);
    if(p->ex)lst[++len]=p;
    else stack[++top]=p;
    travel(p->ch[1]);
}
ScapeGoat_Tree *divide(int  l,int  r)
{
    if(l>r)return null;
    int  mid=(l+r)>>1;
    lst[mid]->ch[0]=divide(l,mid-1);
    lst[mid]->ch[1]=divide(mid+1,r);
    lst[mid]->pushup();
    return lst[mid];
}
inline void rebuild(ScapeGoat_Tree *&p)
{
    len=0;
    travel(p);
    p=divide(1,len);
}
ScapeGoat_Tree **insert(ScapeGoat_Tree *&p,int  key)
{
    if(p==null )
    {
      p=New(key);
      return &null;
    }
    p->size++;
    p->cover++;
    ScapeGoat_Tree **ret=insert(p->ch[p->key<=key],key);
    if(p->bad())ret=&p;
    return ret;
}
inline void Insert(ScapeGoat_Tree *&Root,int  key)
{
    ScapeGoat_Tree **p=insert(Root,key);
    if(*p!=null )rebuild(*p);
}
inline int  Rank_Max(ScapeGoat_Tree *Root,int  key)
{
    ScapeGoat_Tree *now=Root;
    int  ret=0;
    while(now!=null )
     if(now->key<=key)
      now=now->ch[1];
     else
      ret+=now->ch[1]->size+now->ex,now=now->ch[0];
    return ret;
}
inline int  Rank_Min(ScapeGoat_Tree *Root,int key)
{
    ScapeGoat_Tree *now=Root;
    int  ret=0;
    while(now!=null )
     if(now->key>=key)
      now=now->ch[0];
     else
      ret+=now->ch[0]->size+now->ex,now=now->ch[1];
    return ret;
}
void del(ScapeGoat_Tree *p,int k)
{
    p->size--;
    if(p->ex&&p->ch[0]->size+1==k)
    {
      p->ex=0;
      return;
    }
    if(p->ch[0]->size>=k) del(p->ch[0],k);
    else del(p->ch[1],k-p->ch[0]->size-p->ex);
}
inline void Del(ScapeGoat_Tree *&Root,int  key)
{
    del(Root,Rank_Min(Root,key)+1);
    if(Root->size<Root->cover*a)rebuild(Root);
}
int  n,m,pos[MAXN];
void build(Tree *p)
{
     p->mid=(p->l+p->r)>>1;
     if(p->l==p->r)return;
     p->ch[0]=new Tree;
     p->ch[0]->l=p->l;
     p->ch[0]->r=p->mid;
     p->ch[1]=new Tree;
     p->ch[1]->l=p->mid+1;
     p->ch[1]->r=p->r;
     build(p->ch[0]);
     build(p->ch[1]);
}
void Ins(Tree *p,int  key,int  aim)
{
     Insert(p->root,key);
     if(p->l==p->r)return;
     Ins(p->ch[p->mid<aim],key,aim);
}
int  query_Max(int  l,int  r,int  key,Tree *p)
{
     if(l<=p->l&&p->r<=r)
        return Rank_Max(p->root,key);
     int  tmp=0;
     if(l<=p->mid)tmp+=query_Max(l,r,key,p->ch[0]);
     if(p->mid<r)tmp+=query_Max(l,r,key,p->ch[1]);
     return tmp;
}
int  query_Min(int  l,int  r,int  key,Tree *p)
{
     if(l<=p->l&&p->r<=r)
      return Rank_Min(p->root,key);
     int  tmp=0;
     if(l<=p->mid)tmp+=query_Min(l,r,key,p->ch[0]);
     if(p->mid<r)tmp+=query_Min(l,r,key,p->ch[1]);
     return tmp;
}
void Delete(Tree *p,int  key,int  aim)
{
     Del(p->root,key);
     if(p->l==p->r)return;
     Delete(p->ch[p->mid<aim],key,aim);
}
int main()
{
    //freopen("nt2011_queue.in","r",stdin);
    //freopen("nt2011_queue.out","w",stdout);
    Init();
    scanf("%d",&n);
    root=new Tree;
    root->l=1;
    root->r=n;
    build(root);
    for(int  i=1;i<=n;i++)
    {
      int x;
      scanf("%d",&x);
      pos[i]=x;
      Ins(root,x,i);
      if(i!=1)ans+=query_Max(1,i-1,x,root);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
      printf("%lld\n",ans);
      int  x,y;
      scanf("%d%d",&x,&y);
      if(x!=1) ans-=query_Max(1,x-1,pos[x],root);
      if(x!=n) ans-=query_Min(x+1,n,pos[x],root);
      Delete(root,pos[x],x);
      if(y!=1) ans-=query_Max(1,y-1,pos[y],root);
      if(y!=n) ans-=query_Min(y+1,n,pos[y],root);
      Delete(root,pos[y],y);
      swap(pos[x],pos[y]);
      Ins(root,pos[x],x);
      if(x!=1) ans+=query_Max(1,x-1,pos[x],root);
      if(x!=n) ans+=query_Min(x+1,n,pos[x],root);
      Ins(root,pos[y],y);
      if(y!=1) ans+=query_Max(1,y-1,pos[y],root);
      if(y!=n) ans+=query_Min(y+1,n,pos[y],root);
    }
    printf("%lld\n",ans);
    return 0;
}

 

【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树