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