[CQOI2011] Dynamic reverse order pair

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324846898&siteId=291194637