对于每一个位置我们处理出刚开始它左边比他大的数的个数,和它右边比它小的数的个数,然后每次删除就在主席树里修改,最后答案就要减去a1+a2-左边比他大的被删除了的数的个数-右边比他小的被删除了的数的个数。
一开始傻逼了,还对整个序列建前缀主席树,还以为省空间,结果发现树状数组直接预处理就好了,最后在不断地RE过程中,艰难的A了,看来卡空间的题真是非常不爽呢。
#include
#include
#include
#include
#include
#include
#define maxn 10000010
using namespace std;
int lch[maxn],rch[maxn],cnt[maxn];
int s[100010],root[100010],a[100010];
int l[30],r[30],rank[100010];
int n,T,tot,llen,rlen,a1[100010],a2[100010];
long long ans;
int lowbit(int i)
{
return i&(-i);
}
long long query(int i)
{
long long ans=0;
while (i)
{
ans+=s[i];
i-=lowbit(i);
}
return ans;
}
void add(int i,int x)
{
while (i<=n)
{
s[i]+=x;
i+=lowbit(i);
}
}
int modify(int pre,int l,int r,int x,int f)
{
int now=++tot;
if (l==r)
{
cnt[now]=cnt[pre]+f;lch[now]=rch[now]=0;
}
else
{
int mid=(l+r)/2;
if (x<=mid)
{
rch[now]=rch[pre];lch[now]=modify(lch[pre],l,mid,x,f);
}
else
{
lch[now]=lch[pre];rch[now]=modify(rch[pre],mid+1,r,x,f);
}
cnt[now]=cnt[lch[now]]+cnt[rch[now]];
}
return now;
}
void modify(int x,int t,int f)
{
for (int i=x;i<=n;i+=lowbit(i)) root[i]=modify(root[i],1,n,t,f);
}
long long query(int L,int R,int x,int y)
{
if (x>y) return 0;
if (L==x && R==y)
{
long long sum=0;
for (int i=1;i<=llen;i++) sum-=cnt[l[i]];
for (int i=1;i<=rlen;i++) sum+=cnt[r[i]];
return sum;
}
int mid=(L+R)/2;
if (y<=mid)
{
for (int i=1;i<=llen;i++) l[i]=lch[l[i]];
for (int i=1;i<=rlen;i++) r[i]=lch[r[i]];
return query(L,mid,x,y);
}
if (mid=1;i--)
{
ans+=query(a[i]);a2[i]=query(a[i]);
add(a[i],1);
}
memset(s,0,sizeof(s));
for (int i=1;i<=n;i++)
{
a1[i]=query(n)-query(a[i]);
add(a[i],1);
}
for (int i=1;i<=n;i++) rank[a[i]]=i;
tot=0;root[0]=lch[0]=rch[0]=cnt[0]=0;
for (int i=1;i<=n;i++) root[i]=root[0];
while (T--)
{
printf("%lld\n",ans);
int x,pos;
scanf("%d",&x);
pos=rank[x];
llen=0;rlen=0;
for (int i=pos-1;i;i-=lowbit(i)) r[++rlen]=root[i];
ans+=query(1,n,x+1,n);
llen=0;rlen=0;
for (int i=pos;i;i-=lowbit(i)) l[++llen]=root[i];
for (int i=n;i;i-=lowbit(i)) r[++rlen]=root[i];
ans+=query(1,n,1,x-1);
ans-=a1[pos]+a2[pos];
modify(pos,x,1);
}
return 0;
}