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;
}