zoukankan      html  css  js  c++  java
  • 【POJ】3378 Crazy Thairs(树状数组+dp+高精)

    题目

    传送门:QWQ

    分析

    题意:给个数列,求有多少五元上升组

    考虑简化一下问题:如果题目求二元上升组怎么做。

    仿照一下逆序对,用树状数组维护一下就ok了。

    三元怎么做呢?

    把二元的拓展一位就可以了,即把第三个也扔进树状数组

    所以这题就渐渐明朗了:

    用$ dp[i][x] $表示以$ A[x] $结尾的$ x $元上升组有多少个

    那么:

    $ dp[i][x]=sum_{j=1}^{i-1} dp[j][x-1] (A[j]<A[i]) $

    其中 $ dp[i][1]=1 $

    因为多了一位大的就加了一位嘛

    但这个看起来是$ O(n^2) $的,肯定要凉,所以扔进树状数组优化一下。

    对了,这题还要离散化和高精度 

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn=50010,N = 50010, Base = 10000000;
    typedef long long LL; 
    class BigNum { 
    public:  
        int num[7], len;  
        BigNum():len(0) {}  
        BigNum(int n):len(0) {   for( ; n > 0; n /= Base) num[len++] = n%Base;   }  
        BigNum Bigvalueof(LL n) {  
            len = 0;   while(n) {   num[len++] = n%Base;   n /= Base;   }  
            return *this;  
        }  
        BigNum operator + (const BigNum& b) {   
            BigNum c;   int i, carry = 0;  
            for(i = 0; i < this->len || i < b.len || carry > 0; ++i) {  
                if(i < this->len)   carry += this->num[i];  
                if(i < b.len)   carry += b.num[i];  
                c.num[i] = carry%Base;   carry /= Base;  
            }  
            c.len = i;   return c;  
        } 
        BigNum operator += (const BigNum& b) {  *this = *this + b;   return *this;   }  
        void Print() {  
            if(len == 0)    {puts("0"); return ;}  
            printf("%d", num[len - 1]);  
            for(int i = len - 2; i >= 0; --i) 
                for(int j = Base/10; j > 0; j /= 10) 
                    printf("%d", num[i]/j%10);  
            puts("");  
        }  
    };
    typedef BigNum bign;
    int n;
    bign sum[maxn][8]; 
    struct Node{
        int v,pos;
        bool operator < (const Node& a) const{ return v<a.v; }
    }a[maxn];
    void add(int x,int e,bign a){for(;x<=n;x+=x&-x)sum[x][e]+=a;}
    bign summ(int x,int e){bign ans;for(;x>0;x-=x&-x)ans+=sum[x][e];return ans;}
    int main(){
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++){scanf("%d",&a[i].v);a[i].pos=i;}
            sort(a+1,a+1+n); memset(sum,0,sizeof(sum));
            int cnt=0;
            bign ans=0;
            for(int i=1;i<=n;i++){
                add(a[i].pos,1,1);
                for(int j=2;j<=5;j++){
                    add(a[i].pos,j,summ(a[i].pos-1,j-1));
                }
            }
            summ(n,5).Print();
        }
        return 0;
    }
  • 相关阅读:
    How to create jar for Android Library Project
    Very large tabs in eclipse panes on Ubuntu
    64bit Ubuntu, Android AAPT, R.java
    Linux(Ubuntu)下如何安装JDK
    Configure xterm Fonts and Colors for Your Eyeball
    建立、配置和使用Activity——启动其他Activity并返回结果
    建立、配置和使用Activity——使用Bundle在Activity之间交换数据
    建立、配置和使用Activity——启动、关闭Activity
    建立、配置和使用Activity——Activity
    异步任务(AsyncTask)
  • 原文地址:https://www.cnblogs.com/noblex/p/9229175.html
Copyright © 2011-2022 走看看