zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    [CSP-S模拟测试]:F(DP+线段树)
    [CSP-S模拟测试]:E(贪心)
    [CSP-S模拟测试]:D(暴力+剪枝)
    [CSP-S模拟测试]:C(三分+贪心)
    [CSP-S模拟测试]:B(DP+数学)
    [CSP-S模拟测试]:A(数学)
    [CSP-S模拟测试]:密码(数位DP+库默尔定理)
    BZOJ3456 城市规划 【多项式求逆】
    多项式求逆
    uoj185 [ZJOI2016]小星星 【dp + 容斥】
  • 原文地址:https://www.cnblogs.com/chen9510/p/5730684.html
Copyright © 2011-2022 走看看