For a sequence A, its inverse logarithm is defined as the number of pairs (i, j) that satisfy i<j and Ai>Aj. Given a permutation of 1 to n, delete m elements in some order (without restoration), your task is to count the inverse logarithm of the entire sequence before deleting one element at a time.
The first reaction to see the title, the tree array is messing around?
Location line segment tree set weight tree array? Explosive space!
solution:
1. Blocked tree array violence,Don't talk about
2. Tree set tree There are two
known ways of writing:
position tree array, weight line segment tree
Weight tree array, position line segment tree
Here write weight tree array, position line segment tree
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxsize 6000005//具体多小试试看
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
int root[maxsize],lson[maxsize],rson[maxsize],sum[maxsize],sz;
int val[100005],pos[100005];
int bb[100005],as[100005];//before_bigger after_smaller
LL ans;
int n,m;
inline int read() {
int sum=0;char ch=0;
while (ch>'9' || ch<'0') ch=getchar();
while (ch>='0' && ch<='9') sum=sum*10+ch-'0',ch=getchar();
return sum;
}
inline void update1(int x) {
for (;x<=n;x+=lowbit(x)) root[x]++;
}
inline int getsum1(int x) {
int sum=0;
for (;x>0;x-=lowbit(x)) sum+=root[x];
return sum;
}
int query(int pp,int l,int r,int ll,int rr) {
if (pp==0) return 0;
if (l==ll && r==rr) return sum[pp];
int mid=(l+r)>>1;
if (rr<=mid) return query(lson[pp],l,mid,ll,rr);
if (ll>mid) return query(rson[pp],mid+1,r,ll,rr);
return query(lson[pp],l,mid,ll,mid)+query(rson[pp],mid+1,r,mid+1,rr);
}
void update(int &pp,int l,int r,int ll) {
if (pp==0) {
pp=++sz;
if (sz>=maxsize) puts("MLE");
}
sum[pp]++;
if (l==r && l==ll) return;
int mid=(l+r)>>1;
if (ll<=mid) update(lson[pp],l,mid,ll);
else update(rson[pp],mid+1,r,ll);
}
inline int query_bb(int v,int p) {//值比它大,在它前面
int sum1=0,sum2=0,x=n;
for (;v;v-=lowbit(v)) sum1+=query(root[v],1,n,1,p);
for (;x;x-=lowbit(x)) sum2+=query(root[x],1,n,1,p);
return sum2-sum1;
}
inline int query_as(int v,int p) {//值比它小,在它后面
int sum=0;
for (;v;v-=lowbit(v)) sum+=query(root[v],1,n,p,n);
return sum;
}
inline void update2(int v,int p) {
for (;v<=n;v+=lowbit(v)) update(root[v],1,n,p);
}
int main() {
n=read();m=read();
for (int i=1;i<=n;i++) {
val[i]=read();
pos[val[i]]=i;
bb[i]=getsum1(n)-getsum1(val[i]);//借用一下root[]
ans+=bb[i];
update1(val[i]);
}
memset(root,0,sizeof(root));
for (int i=n;i>0;i--) {
as[i]=getsum1(val[i]-1);
update1(val[i]);
}
memset(root,0,sizeof(root));
while (m--) {
printf("%lld\n",ans);
int v=read(),p=pos[v];
ans-=(bb[p]+as[p]-query_as(v-1,p+1)-query_bb(v,p-1));
update2(v,p);
}
return 0;
}
3. cdq divide and conquer
This is a pot, make up for it in a few days