题目
求长度为5的最长上升子序列个数
分析
可以用树状数组实现,然而改了几个月的原因,就是高精度,可以说,不算大,但爆了long long
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rr register
using namespace std;
unsigned n;
unsigned r[51000],s[51000],tmp[51000];
const int inf=1000000000;
struct Bigint{
int a,b,c;
void add(Bigint y){//高精度
c+=y.c; if(c>=inf) c-=inf,b++;
b+=y.b; if(b>=inf) b-=inf,a++;
a+=y.a;
}
void print(){
if(a) printf("%d%09d%09d\n",a,b,c);
else if(b) printf("%d%09d\n",b,c);
else printf("%d\n",c);
}
void init_(){
a=b=c=0;
}
}tree[5][51000];
signed cmp(int a,int b){return s[a]<s[b];}
inline void deal(){//预处理
rr int now;
for(rr int i=0;i<n;++i) tmp[i]=i;
sort(tmp,tmp+n,cmp);
r[tmp[0]]=now=1;
for(rr int i=1;i<n;++i)
if(s[tmp[i]]==s[tmp[i-1]])
r[tmp[i]]=now;
else r[tmp[i]]=++now;
}
inline Bigint query(int i,int val){//求答案
rr Bigint sum;
sum.init_();
if(i<0){
sum.c=1;
return sum;
}
while(val) sum.add(tree[i][val]),val-=val&-val;
return sum;
}
void update(int i,int val){//更新树状数组
rr Bigint temp=query(i-1,val-1);
while(val<=n) tree[i][val].add(temp),val+=val&-val;
}
inline signed in(){
rr int ans=0; rr char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
int main(){
while(scanf("%d",&n)==1){
for(rr int i=0;i<n;++i) s[i]=in();
if(n<5){//不可能产生
putchar(48);
putchar(10);
continue;
}
deal();
for(rr int i=0;i<5;++i)
for(rr int j=1;j<=n;++j)//预处理
tree[i][j].init_();
for(rr int j=0;j<n;++j)
for(rr int i=0;i<5;++i)//更新树状数组
update(i,r[j]);
query(4,n).print();//输出答案
}
return 0;
}