首页 > 代码库 > BZOJ3295: [Cqoi2011]动态逆序对 莫队

BZOJ3295: [Cqoi2011]动态逆序对 莫队

这个用莫队做会被卡,但是我还是......

收获在于树状数组维护后缀和以及双维排序......

莫队的时间复杂度比想象中的要好一些....

然而我还是被卡了......

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define MAXN 100005
using namespace std;
int pos[MAXN],len,a[MAXN],front[MAXN],back[MAXN],n,m,t[MAXN],p,now,b[MAXN],live[MAXN];
struct Q
{
   int pos,time,ans;
}q[MAXN];
int comp(const Q x,const Q y)
{
   return pos[x.pos]<pos[y.pos]||(pos[x.pos]==pos[y.pos]&&x.time<y.time);
}
int end_comp(const Q x,const Q y)
{
   return x.time<y.time;
}
inline int lowbit(int x)
{
   return x&(-x);
}
inline void update_front(int x,int i)
{
   if(x==0)return;
   while(x>0)
   {
     front[x]+=i;
     x-=lowbit(x);
   }
}
inline void update_back(int x,int i)
{
   if(x==0)return;
   while(x<=n)
   {
     back[x]+=i;
     x+=lowbit(x);  
   }
}
inline int sum_front(int x)
{
   int ret=0;
   while(x<=n)
   {
     ret+=front[x];
     x+=lowbit(x);
   }
   return ret;
}
inline int sum_back(int x)
{
   int ret=0;
   while(x>0)
   {
     ret+=back[x];
     x-=lowbit(x); 
   }
   return ret;
}
long long ans;
void pre()
{
    scanf("%d%d",&n,&m);
    len=(int)(sqrt(n+0.5));
    for(int i=1;i<=n;i++)
    {
      scanf("%d",&a[i]);
      live[a[i]]=i;
      pos[i]=(i-1)/len+1;
    }
    for(int i=n;i>0;i--)
    {
      ans+=sum_back(a[i]-1);
      update_back(a[i],1);
    }
    update_back(a[1],-1);
    p=1;
    now=1;
    for(int i=1;i<=m;i++)
    {
      scanf("%d",&b[i]);
      q[i].pos=live[b[i]];
      q[i].time=i;
    }
    sort(q+1,q+m+1,comp);
}
inline void via(int pl,int i)
{
    a[live[pl]]=(i==1)?pl:0;
    if(live[pl]<p)update_front(pl,i);
    if(live[pl]>p)update_back(pl,i);
}
inline void do_front(int pl)
{
    update_front(a[pl],1);
    update_back(a[pl+1],-1);
}
inline void do_back(int pl)
{
    update_back(a[pl],1);
    update_front(a[pl-1],-1);
}
void work()
{
    for(int i=1;i<=m;i++)
    {
       while(now<q[i].time)via(b[now++],-1);
       while(now>q[i].time)via(b[--now],1);
       while(p<q[i].pos)do_front(p++);
       while(p>q[i].pos)do_back(p--);
       q[i].ans=sum_front(a[q[i].pos]+1)+sum_back(a[q[i].pos]-1);
    }
}
void print()
{
    sort(q+1,q+m+1,end_comp);
    for(int i=1;i<=m;i++)
    {
      printf("%lld\n",ans);
      ans-=q[i].ans;
    }
}
int main()
{
    //freopen("inverse.in","r",stdin);
    //freopen("inverse.out","w",stdout);
    pre();
    work();
    print();
    return 0;
}

 

BZOJ3295: [Cqoi2011]动态逆序对 莫队