zoukankan      html  css  js  c++  java
  • ●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("
    ");
    	}	
    	return 0;
    }
    

      

  • 相关阅读:
    挖矿是如何产生比特币的?
    影响世界的100个管理定律
    震撼人心的战争类背景音乐
    一个美国女警的工作记录(转载
    李昌镐:苍老的青春(转载)
    博主简介
    python 中判断变量是否定义
    Reading geometries
    Writing geometries
    Accessing data using cursors
  • 原文地址:https://www.cnblogs.com/zj75211/p/8365607.html
Copyright © 2011-2022 走看看