HDU 5792---2016暑假多校联合---World is Exploding

2016暑假多校联合---World is Exploding

Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: abcd,1a<bn,1c<dn,Aa<Ab,Ac>Ad.
 

 

Input
The input consists of multiple test cases. 
Each test case begin with an integer n in a single line.

The next line contains n integers A1,A2An.
1n50000
0Ai1e9
 

 

Output
For each test case,output a line contains an integer.
 

 

Sample Input
4 2 4 1 3 4 1 2 3 4
 

 

Sample Output
1 0
 
题意肯简单;
 
思路:先将输入的n个数进行离散化处理得到A[],使每个数小于50000,然后就可以使用树状数组求出 在第i个数时 在1~i-1中比A[i]大的个数、在1~i-1中比A[i]小的个数、在i+1~n中比A[i]小的个数、在i+1~n中比A[i]大的个数,即得到对应数组a1[]、b1[]、a2[]、b2[]  ; 很容易用树状数组求出A[]数组中逆序数的个数num1及上升的数对的个数num2,sum=num1*num2, 再一个循环sum=sum-a1[i]*a2[i]-b1[i]*b2[i]-a1[i]*b1[i]-a2[i]*b2[i],最后sum即为结果;
 
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=50005;
typedef long long LL;
LL Scan()///输入外挂
{
    LL res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}

void Out(LL a)///输出外挂
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}
long long A[50005];
long long B[50005];
map<long long,long long>p;

long long c[N];
long long a1[N],a2[N];  ///小;
long long b1[N],b2[N];  ///大;

long long Lowbit(long long t)
{
    return t&(t^(t-1));
}

void update(long long x)
{
    while(x>0)
    {
        c[x]++;
        x -= Lowbit(x);
    }
}

long long Sum(long long li)
{
    long long sum=0;
    while(li<N)
    {
        sum+=c[li];
        li=li+Lowbit(li);
    }
    return sum;
}

int main()
{
    long long n;
    long long sum;
    while(scanf("%lld",&n)!=EOF)
    {
        sum=0;
        for(int i=0;i<n;i++)
        {
            A[i] = Scan();
            B[i]=A[i];
        }
        sort(B,B+n);
        long long tot=0,pre=0;
        for(int i=0;i<n;i++)  ///离散化,
        {
            if(B[i]==pre)
                B[i]=tot;
            else
            {
                pre=B[i];
                B[i]=++tot;
                p[pre]=tot;
            }
        }
        for(int i=0;i<n;i++)
            A[i]=p[A[i]];

        long long num1=0;
        long long num2=0;
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            num1+=Sum(A[i]+1);
            update(A[i]);
        }
        memset(c,0,sizeof(c));
        for(int i=n-1;i>=0;i--)
        {
            num2+=Sum(A[i]+1);
            update(A[i]);
        }
        sum=num1*num2;
        ///cout<<"num1: "<<num1<<" num2: "<<num2<<" sum: "<<sum<<endl;

        memset(a1,0,sizeof(a1));
        memset(a2,0,sizeof(a2));
        memset(b1,0,sizeof(b1));
        memset(b2,0,sizeof(b2));
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            a1[i]=Sum(N-A[i]+1);
            update(N-A[i]);
        }

        memset(c,0,sizeof(c));
        for(int i=n-1;i>=0;i--)
        {
            a2[i]=Sum(N-A[i]+1);
            update(N-A[i]);
        }

        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            b1[i]=Sum(A[i]+1);
            update(A[i]);
        }

        memset(c,0,sizeof(c));
        for(int i=n-1;i>=0;i--)
        {
            b2[i]=Sum(A[i]+1);
            update(A[i]);
        }
        for(int i=0;i<n;i++)
        {
            sum-=a1[i]*a2[i];
            sum-=a1[i]*b1[i];
            sum-=a2[i]*b2[i];
            sum-=b1[i]*b2[i];
        }
        Out(sum);
        puts("");
    }
    return 0;
}

 

posted @ 2016-08-02 20:56  茶飘香~  阅读(178)  评论(0编辑  收藏  举报