●POJ 3378 Crazy Thairs

题链:

http://poj.org/problem?id=3378

题解:

树状数组维护,高精度。

依次考虑以每个位置结尾可以造成的贡献。

假设当前位置为i,为了达到5个元素的要求,我们需要求出,在序列1~i-1中有多少个合法4元组$(a<b<c<d且A_a<A_b<A_c<A_d)$的最后那个元素是小于$A_i$的$(即为了满足a<b<c<d<i且A_a<A_b<A_c<A_d<A_i)$,求出这种四元组的个数,那么就是以i位置结尾可以贡献的答案。

所以我们用树状数组"D4"维护以权值x结尾的合法四元组的个数,那么对于当前的A_i,就只需要查询树状数组的[1~A_i-1]的区间的和,这个和便是应该贡献的答案。

然而为了维护以某一元素结尾的合法四元组的个数,我们不得不再用一个树状数组"D3"维护以权值x结尾的合法三元组的个数。

同理,为了维护以某一元素结尾的合法三元组的个数,还需要一个树状数组"D2"维护以权值x结尾的合法二元组的个数,然后是一个树状数组"D1"维护以权值x结尾的合法一元组的个数。。。。。。

然后就只需要对于依次枚举到的第i个元素,进行查询和更新树状数组就好了。

(本体比较恶心,爆longlong,就再弄一个高精度咯。)

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50050
#define ll long long
using namespace std;
struct BigInt{
	#define Bit 1000
	int val[10],len;
	BigInt(){len=1;memset(val,0,sizeof(val));}
	void operator = (int rtm){
		memset(val,0,sizeof(val));
		len=0; do{
			val[++len]=rtm%Bit; rtm/=Bit;
		}while(rtm);
	}
	BigInt operator + (const BigInt &rtm) const{
		BigInt now; now.len=max(rtm.len,len);
		for(int i=1;i<=now.len;i++){
			now.val[i]+=val[i]+rtm.val[i];
			now.val[i+1]+=now.val[i]/Bit;
			now.val[i]%=Bit;
		}
		while(now.val[now.len+1]) now.len++;
		return now;
	}
	void Print(){
		printf("%d",val[len]);
		for(int i=len-1;i;i--) printf("%03d",val[i]);
	}
};
struct BIT{
	BigInt val[MAXN]; int n;
	int Lowbit(int x){return x&-x;}
	void Reset(int _n){n=_n; while(_n) val[_n]=0,_n--;}
	void Modify(int p,BigInt v){
		while(p<=n) val[p]=val[p]+v,p+=Lowbit(p);
	}
	BigInt Query(int p){
		static BigInt ret; ret=0;
		while(p) 
			ret=ret+val[p],p-=Lowbit(p);
		return ret;
	}
}D1,D2,D3,D4;
int A[MAXN],tmp[MAXN];
int N,tnt;
BigInt ANS,t,one;
int main(){
	one=1;
	while(~scanf("%d",&N)){
		for(int i=1;i<=N;i++) 
			scanf("%d",&A[i]),tmp[i]=A[i];
		sort(tmp+1,tmp+N+1);
		tnt=unique(tmp+1,tmp+N+1)-tmp-1;
		for(int i=1;i<=N;i++)
			A[i]=lower_bound(tmp+1,tmp+tnt+1,A[i])-tmp;
		D1.Reset(tnt); D2.Reset(tnt);
		D3.Reset(tnt); D4.Reset(tnt); ANS=0;
		for(int i=1;i<=N;i++){
			D1.Modify(A[i],one); t=D1.Query(A[i]-1);
			D2.Modify(A[i],t); t=D2.Query(A[i]-1);
			D3.Modify(A[i],t); t=D3.Query(A[i]-1);
			D4.Modify(A[i],t); 
			t=D4.Query(A[i]-1);
			ANS=ANS+t;
		}
		ANS.Print(); printf("\n");
	}	
	return 0;
}

  

 

posted @ 2018-01-27 13:16  *ZJ  阅读(128)  评论(0编辑  收藏  举报