zoukankan      html  css  js  c++  java
  • [POJ 3378] Crazy Thairs

    Link:

    POJ 3378 传送门

    Solution:

    按序列长度$dp$,

    设$dp[i][j]$为到第$i$个数,符合要求的序列长度为$j$时的序列个数,

    易得转移方程:$dp[i][j]=sum_{k=1}^{i-1} dp[k][j-1] (dat[k]<dat[i])$

    用树状数组按$dat[i]$为坐标来维护$dp[i][j-1]$的值即可,

    由于$dat[i] le 1e9$,记得离散化,同时答案超过$long long$,要高精度

    这里可以选择开5个树状数组,也可以只用一个树桩数组,每次维护$dp[][j-1]$的值后清空

    由于此题卡空间,推荐我用的第二种

    如果要用第一种,要用到高精度的一些黑科技,改为10000进制,这样只要7位就行了Orz

    10000进制的输出:

    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("");
    }

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    
    using namespace std;
    const int MAXN=5e4+10;
    int T,dsp[MAXN],n,dat[MAXN],tot=0;
    
    struct BI //高精度类
    {
        int d[25],len;
        
        BI() {memset(d,0,sizeof(d));len=1;}
        void clean(){memset(d,0,sizeof(d)),len=1;}
        BI(int num) {*this=num;}
        
        BI& operator = (const int& num)
        {
            memset(d,0,sizeof(d));
            int temp=num;len=0;
            while(temp)
                d[++len]=temp%10,temp/=10;
            return *this;
        }
        
        BI operator + (const BI& num)
        {
            BI ret;ret=*this;
            ret.len=max(len,num.len);
            for(int i=1;i<=ret.len;i++)
            {
                ret.d[i]+=num.d[i];
                if(ret.d[i]>=10)
                    ret.d[i]-=10,ret.d[i+1]++;
            }
            if(ret.d[ret.len+1]) ret.len++;
            return ret;
        }
        BI operator += (const BI& num){*this=*this+num;return *this;}
        void print(){for(int i=len;i>=1;i--) printf("%d",d[i]);}
    }bit[MAXN],dp[MAXN][6],res;
    
    void Update(int pos,BI val){while(pos<=n) bit[pos]+=val,pos+=pos&(-pos);}
    BI Query(int pos)
    {
        BI ret=0; //记得初始化
        while(pos) ret+=bit[pos],pos-=pos&(-pos);
        return ret;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++) scanf("%d",&dat[i]),dsp[i]=dat[i]; //离散化
            sort(dsp+1,dsp+n+1);tot=unique(dsp+1,dsp+n+1)-dsp-1;
            for(int i=1;i<=n;i++) dat[i]=lower_bound(dsp+1,dsp+tot+1,dat[i])-dsp;
            
            res.clean();
            for(int i=0;i<n+5;i++) for(int j=0;j<6;j++) dp[i][j].clean();
            for(int i=1;i<=n;i++) dp[i][1]=(BI)1;
            for(int i=2;i<=5;i++)
            {
                for(int j=0;j<tot+5;j++) bit[j].clean();
                for(int j=1;j<=n;j++)
                    dp[j][i]=Query(dat[j]-1),Update(dat[j],dp[j][i-1]);
            }
            for(int i=1;i<=n;i++) res+=dp[i][5];
            res.print();puts("");
        }
        return 0;
    }

    Review:

    一道比较常规的题吧,用到了离散化和高精度的一些套路

    (1)如果$dp$复杂度有问题,可以向单调性/斜率优化/RMQ维护上想一想

    (2)犯的丝帛错误:

    $Query$函数里的$ret$要预处理!!!

    (3)黑科技:高精度空间不够时转为更高进制(10000进制) 

  • 相关阅读:
    透明的LISTVIEW
    循序渐进实现仿QQ界面(三):界面调色与控件自绘
    循序渐进实现仿QQ界面(一):园角矩形与双缓冲贴图窗口
    循序渐进实现仿QQ界面(二):贴图按钮的三态模拟
    C#中如何通过点击按钮切换窗口
    jQuery -- 光阴似箭(二):jQuery效果的使用
    jQuery -- 光阴似箭(一):初见 jQuery -- 基本用法,语法,选择器
    JavaScript -- 时光流逝(十三):DOM -- Console 对象
    JavaScript -- 时光流逝(十二):DOM -- Element 对象
    JavaScript -- 时光流逝(十一):DOM -- Document 对象
  • 原文地址:https://www.cnblogs.com/newera/p/9157322.html
Copyright © 2011-2022 走看看