• 【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;
    }
  • 相关阅读:
    Spring源码分析(五)获取Document
    Spring源码分析(四)容器的基础XmlBeanFactory
    Spring源码分析(三)容器核心类
    Spring源码分析(二)容器基本用法
    day23 框架之基础加强
    Java web项目综合练习(Estore)
    第16 天 JavaWEB过滤器和监听器技术
    第17天 笔记 文件上传下载
    Javaweb 第15天 web练习和分页技术
    【剑指offer】数组中的逆序对,C++实现
  • 原文地址:https://www.cnblogs.com/noblex/p/9229175.html
Copyright © 2020-2023  润新知