[National Training Team] Queue

Luogu

Description

Sitting in rows, eating fruit, the fruit is sweet and long, and everyone laughs. One for you, one for me, the big one will be given to you, and the small one for me. After eating Guoguo, you will sing a song, and everyone will be happy and harmonious.
The children of Hongxing Kindergarten lined up in a long line, ready to eat fruit. However, because the heights of the children are different, the ranks of the children are disordered, which is extremely unsightly. Let the height of the i-th child be hi, and we define the disorder degree of a sequence as: the number of \((i,j)\)
that satisfies \(i<j\) and \(h_i>h_j\) .

The kindergarten aunt will select two children each time and exchange their positions. Please help to calculate the clutter of the sequence after each exchange. In order to facilitate the statistics of the kindergarten aunt, you should also output the clutter of the sequence when no swap operation is performed.

Input

The first line is a positive integer n, which represents the number of children;
the second line contains n positive integers h1, h2, ..., hn separated by spaces, which in turn represent the height of the children in the initial queue;
the third line is a positive integer m, Indicates the number of swap operations;
each of the following m lines contains two positive integers ai and bi, representing the children who exchange positions ai and bi.

Output

The output file has m+1 lines in total, and a positive integer in the i-th line indicates the disorder degree of the sequence after the exchange operation i is completed.

Range

对于 100% 的 数据 ,\ (1 \ leq m \ leq 2 \ times 10 ^ 3,1 \ leq n \ leq 2 \ times 10 ^ 4,1 \ leq h_i \ leq 10 ^ 9, a_i \ ne b_i, 1 \ leq a_i, b_i \ leq n \)

Solution

There is a practice of prefixes and ideas here.
This idea was inspired by poetry .
In that question, we borrowed the prefix sum to count the number of occurrences of each number, and this question is completely OK!
Definition \(sum[i][j]\) represents the number of occurrences of a child with a height of \(j\) in the \(1-i\) th block. After all the heights are discretized first, the answer without any operation is first obtained from the tree array. Then you can update the current with the help of previous answers, and the big guy downstairs will not be verbose. For swap \([l,r]\) , corner violence, within-block statistical answers. How to count it? From the formula of the big guy downstairs, we can know that if \(a[i]<val[l]\) and \(a[i]>val[r]\) , then \(ans++\) . This is to loop \(i\) from \(belong[l]+1\) to \(belong[r]-1\) . Another way of thinking, what if \(i\) represents not an element, but a value? That is, looping \(i\) from 1 to the range, then if





\(i<val[l]\) and \(i>val[r]\) , then \(ans\) will become larger.
How much does it get bigger? This value is \(sum[belong[r]-1][i]-sum[belong[l]][i]\) .
The same is true for the other three cases, then each time the answer is finished.
Remember to update the \(sum\) array!

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 20005
#define int long long

int f[N],len;
int n,m,tot,ans;
int sum[150][N];
int val[N],t[N];
int l[150],r[150];
int block,belong[N];

int ask(int x){
    int b=0;
    for(;x;x-=x&-x)
        b+=f[x];
    return b;
}

void add(int x){
    for(;x<=n;x+=x&-x)
        f[x]++;
}

int query(int a,int b){
    //printf("a=%lld,b=%lld\n",a,b);
    if(val[a]==val[b]) return ans;
    if(belong[a]==belong[b] or belong[a]+1==belong[b]){
        //puts("dfgfhhg");
        for(int i=a+1;i<b;i++){
            if(val[i]<val[a]) ans--;
            if(val[i]<val[b]) ans++;
            if(val[i]>val[a]) ans++;
            if(val[i]>val[b]) ans--;
            //printf("i=%lld,val=%lld,ans=%lld\n",i,val[i],ans);
        }
        if(val[a]>val[b]) ans--;
        if(val[a]<val[b]) ans++;
        if(belong[a]+1==belong[b])
            sum[belong[a]][val[a]]--,sum[belong[a]][val[b]]++;
        val[a]^=val[b]^=val[a]^=val[b];
        return ans;
    }
    if(val[a]>val[b]) ans--;
    if(val[a]<val[b]) ans++;
    for(int i=a+1;i<=r[belong[a]];i++){
        if(val[i]<val[a]) ans--;
        if(val[i]<val[b]) ans++;
        if(val[i]>val[a]) ans++;
        if(val[i]>val[b]) ans--;
    }
    for(int i=b-1;i>=l[belong[b]];i--){
        if(val[i]<val[a]) ans--;
        if(val[i]<val[b]) ans++;
        if(val[i]>val[a]) ans++;
        if(val[i]>val[b]) ans--;
    }
    for(int i=1;i<=len;i++){
        if(i<val[a]) ans-=sum[belong[b]-1][i]-sum[belong[a]][i];
        if(i<val[b]) ans+=sum[belong[b]-1][i]-sum[belong[a]][i];
        if(i>val[a]) ans+=sum[belong[b]-1][i]-sum[belong[a]][i];
        if(i>val[b]) ans-=sum[belong[b]-1][i]-sum[belong[a]][i];
    }
    for(int i=belong[a];i<belong[b];i++){
        sum[i][val[a]]--;
        sum[i][val[b]]++;
    }
    val[a]^=val[b]^=val[a]^=val[b];
    /*for(int i=1;i<=tot;i++){
        for(int j=1;j<=len;j++)
            printf("i=%lld,j=%lld,sum=%lld\n",i,j,sum[i][j]);
    }*/
    return ans;
}

void file(){
    freopen("in.txt","r",stdin);
    freopen("out2.txt","w",stdout);
}

signed main(){
    //file();
    scanf("%lld",&n);
    block=sqrt(n);
    tot=n/block;
    if(n%block) tot++;
    for(int i=1;i<=n;i++)
        scanf("%lld",&val[i]),t[i]=val[i],belong[i]=(i-1)/block+1;
    std::sort(t+1,t+1+n);
    len=std::unique(t+1,t+1+n)-t-1;
    for(int i=1;i<=n;i++) val[i]=std::lower_bound(t+1,t+1+len,val[i])-t;
    for(int i=1;i<=tot;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    for(int i=n;i;i--){
        ans+=ask(val[i]-1);
        add(val[i]);
        sum[belong[i]][val[i]]++;
    }
    for(int i=1;i<=tot;i++){
        for(int j=1;j<=len;j++)
            sum[i][j]+=sum[i-1][j];
    }
    scanf("%lld",&m);
    printf("%lld\n",ans);
    while(m--){
        int x,y;
        scanf("%lld%lld",&x,&y);
        if(x>y) x^=y^=x^=y;
        printf("%lld\n",query(x,y));
    }
    return 0;
}

Guess you like

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