[POJ 3378] Crazy Thairs
Link:
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进制)