1. 程式人生 > >#樹狀陣列,高精度#poj 3378 Crazy Thairs

#樹狀陣列,高精度#poj 3378 Crazy Thairs

題目

求長度為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; }