【bzoj3295】[Cqoi2011]动态逆序对 树套树 线段树套替罪羊树

这个东西,关于某个数的逆序对数为在他之前比他大的在他之后比他小的数的数目的和,所以删除之前先把这个减去就好了

人傻自带超大常数,中间由于内存池开小了所以运行错误。

#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("inverse.in","r",stdin);
    //freopen("inverse.out","w",stdout);
    Init();
    scanf("%d%d",&n,&m);
    root=new Tree;
    root->l=1;
    root->r=n;
    build(root);
    for(int  i=1;i<=n;i++)
    {
      int x;
      scanf("%d",&x);
      pos[x]=i;
      Ins(root,x,i);
      if(i!=1)ans+=query_Max(1,i-1,x,root);
    }
    for(int  i=1;i<=m;i++)
    {
      printf("%lld\n",ans);
      int  x;
      scanf("%d",&x);
      if(pos[x]!=1) ans-=query_Max(1,pos[x]-1,x,root);
      if(pos[x]!=n) ans-=query_Min(pos[x]+1,n,x,root);
      Delete(root,x,pos[x]);
    }
    return 0;
}

 

posted @ 2017-06-13 16:13  TS_Hugh  阅读(268)  评论(0编辑  收藏  举报