首页 > 代码库 > POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP

POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP

Crazy Thairs
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 6598 Accepted: 1636

Description

These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ≤ N ≤ 50000) numbers, which  are no more than 109, Crazy Thair is a group of 5 numbers {i, j, k, l, m} satisfying:

1. 1 ≤ i < j < k < l < m  N
2. Ai < Aj < Ak < Al < Am

For example, in the sequence {2, 1, 3, 4, 5, 7, 6},there are four Crazy Thair groups: {1, 3, 4, 5, 6}, {2, 3, 4, 5, 6}, {1, 3, 4, 5, 7} and {2, 3, 4, 5, 7}.

Could you help Sempr to count how many Crazy Thairs in the sequence?

Input

Input contains several test cases. Each test case begins with a line containing a number N, followed by a line containing N numbers.

Output

Output the amount of Crazy Thairs in each sequence.

Sample Input

5
1 2 3 4 5
7
2 1 3 4 5 7 6
7
1 2 3 4 5 6 7

Sample Output

1
4
21

——————————————————分割线————————————————————

题目大意:

给定n个数,求满足

1. 1 ≤ i < j < k < l < m  N
2. Ai < Aj < Ak < Al < Am

的总方案数


思路:

dp[i][j]表示以j为结尾长度为i的序列的方案数,则dp[i][j]=dp[i-1][k],其中a[k]要小于a[j]

因此,要想知道5元组的方案数,就要知道4元组的方案数,4元组又要知道3元组的方案数........当长度为1时,方案数为1

对于统计比a[i]小的元素的个数,用树状数组再简单合适不过了

又对于每个元素的数据范围为10的9次方,而题目给的数的个数为50000个,离散化是必须的


又组合数 C(50000,5)必定超过__int64,所以要用高精度


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define M 50000+10
#define ll long long
#define local1
using namespace std;
int n,ans[50],f[M];
ll c[4][M];
struct node
{
    int x,index;
    bool operator< (const node &A)const
    {
        return x<A.x;
    }
}a[M];
void update(int x,ll v,int k)
{
    for(int i=x;i<=n;i+=i&-i){
        c[k][i]+=v;
    }
}
ll getsum(int x,int k)
{
    ll sum=0;
    for(int i=x;i>0;i-=i&-i){
        sum+=c[k][i];
    }
    return sum;
}
void add(ll s)
{
    int t1[50],t2[50],k=0;
    memset(t1,0,sizeof(t1));memset(t2,0,sizeof(t2));
    while(s>0){
        t2[k++]=s%10;
        s/=10;
    }
    for(int i=0;i<50;++i){
        t1[i]+=t2[i]+ans[i];
        if(t1[i]>=10){
            t1[i+1]=t1[i]/10;
            t1[i]%=10;
        }
        ans[i]=t1[i];
    }
}
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
    freopen("ou.txt","w",stdout);
#endif // local
    while(scanf("%d",&n)!=EOF){
        memset(c,0,sizeof(c));memset(ans,0,sizeof(ans));
        for(int i=0;i<n;++i){
            scanf("%d",&a[i].x);
            a[i].index=i;
        }
        sort(a,a+n);
        int key=1;f[a[0].index]=1;
        for(int i=1;i<n;++i){
            if(a[i].x>a[i-1].x) f[a[i].index]=++key;
            else f[a[i].index]=key;
        }
        for(int i=0;i<n;++i){
            update(f[i],1,0);
            for(int j=1;j<=3;++j){
                update(f[i],getsum(f[i]-1,j-1),j);
            }
            add(getsum(f[i]-1,3));
        }
        int k=49;
        for(;k>=0;--k){
            if(ans[k]) break;
        }
        for(int i=k;i>=0;--i){
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}




POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP