Explanation of P5463 "little fish is lovelier" (enhanced version)

Posted by netrepsa on Fri, 25 Oct 2019 23:57:36 +0200

It's not easy to write a blog. Come and play?

This problem is slightly different from that of dalao. I use the method of merging and sorting qwq.

It should be very clear for you to find the reverse order of merging order. I'm going to talk about how to find the answer to this problem by merging order.

Let's look at the rules first

For example, if there is a set of reverse pairs a[3],a[4], n = 5, then there are 6 reverse pairs in the following ranges: [1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]. We can draw a picture to help us understand:

If there is reverse order for a [l], a [R], as shown in the figure:

Then the number of intervals is included, that is, the contribution of the interval to the answer is (L + 1-1) * (N-R + 1) = L * (N-R + 1).

Then merge and sort.

Note two points:

1. This question uses a variable similar to the prefix sum to record the sum of the positions of all the left halves. When you find it, subtract it from $sum $. Otherwise, it will T (at least I will T)

2. Explosive accuracy. Remember to open int 128 or high precision (anyway, I open int 128 qwq)

code:

// Author : Kasugano_Sora
#include<bits/stdc++.h>
using namespace std;
struct item
{
    int pl , val;
} a[1100000] , b[1100000];
int n;
__int128 ans;
inline __int128 read()
{
    __int128 x = 0 , f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

inline void print( __int128 x )    //int 128 required operations
{
    if(x < 0)
    {
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}
void msort( int l , int r )
{
    if(l == r)
    return ;
    int mid = (l + r) >> 1;
    msort(l , mid);
    msort(mid + 1 , r);
    long long sum = 0LL;        //So called prefix
    for(int i = l ; i <= mid ; i++ )
    {
        sum += 1ll * a[i].pl;
    }
    int i = l , j = mid + 1 , k = l;
    while(1)        //Merge
    {
        if(i > mid || j > r)
        break;
        if(a[i].val <= a[j].val)
        sum -= 1ll * a[i].pl , b[k++] = a[i++];
        else
        {
            ans += sum * 1ll * (n - a[j].pl + 1);
            b[k++] = a[j++];
        }
    }
    if(i > mid) for( ; j <= r ; j++ , k++ )
    {
        b[k] = a[j];
    }
    else for( ; i <= mid ; i++ , k++ )
    {
        b[k] = a[i];
    }
    for(int i = l ; i <= r ; i++ )
    {
        a[i] = b[i];
    }
    return ;
}
int main()
{
//  freopen("1.txt" , "r" , stdin);
    cin >> n;
    for(int i = 1 ; i <= n ; i++ )
    {
        scanf("%d" , &a[i].val);
        a[i].pl = i;
    }
    msort(1 , n);
    print(ans);
    return 0;
}

Topics: PHP