题解说是最速下降问题,表示还没做到过,dp方程很好理解,关键是要求数量和同时不能重复,
NOCOW上的方法是
对于第二问求最长下降序列的数量,可以通过求第一问的过程解决。设MaxCnt[i]为第i项为末尾中最长下降序列的个数。
对于所有的j(1≤j≤i-1)如果有(s[j]>s[i] 并且 MaxLength[j]+1>MaxLength[i])则MaxCnt[i]=MaxCnt[j],否则如果(MaxLength[j]+1= =MaxLength[i])可利用加法原理,MaxCnt[i]=MaxCnt[i]+MaxCnt[j]。
考虑到题目中说的不能又重复的序列,我们可以增加一个域Next[i]表示大于i且离i最近的Next[i]使得第Next[i]个数与第i个数相同。如果不存在这样的数则Next[i]=0。这样我们在DP的时候如果出现Next[j]不为0且Next[j]<i可直接跳过。
这个题数据规模很大,用高精.
最后在末尾+个0,直接求到0的最长即可,记住长度最后-1.
一点碎碎念:昨天刚被老师怒骂一顿,唉,论文实在是不会弄了,硬着头皮上了。
/* ID: hubiao cave PROG: buylow LANG: C++ */ #include<iostream> #include<fstream> #include<string> #include<cstring> #include<vector> using namespace std; vector<string> ve; int N; long price[5002]; int nextp[5002]; ifstream fin("buylow.in"); ofstream fout("buylow.out"); //找的高精 class LLint { private: const static int memLen=64; char mem[memLen]; int len; public: LLint() { memset(mem,0,sizeof(mem)); len=0; } LLint(int n) { len=0; while(n) { mem[memLen-1-len++]=n%10+'0'; n/=10; } } LLint(const LLint& rhs) { this->len=rhs.len; memcpy(this->mem,rhs.mem,memLen); } const LLint operator + (const LLint& rhs) { char buf[memLen]={0}; memcpy(buf,this->mem,sizeof(this->mem)); int Ex=0; int i; for(i=0;i<rhs.len;i++) { buf[memLen-1-i]=(buf[memLen-1-i]?buf[memLen-1-i]:'0')-'0'+rhs.mem[memLen-1-i]-'0'+Ex; if(buf[memLen-1-i]>=10) buf[memLen-1-i]=buf[memLen-1-i]-10+'0',Ex=1; else buf[memLen-1-i]+='0',Ex=0; } while(Ex) { buf[memLen-1-i]=(buf[memLen-1-i]?buf[memLen-1-i]:'0')-'0'+Ex; if(buf[memLen-1-i]>=10) buf[memLen-1-i]=buf[memLen-1-i]-10+'0',Ex=1; else buf[memLen-1-i]+='0',Ex=0; i++; } LLint l; if(buf[memLen-max(this->len,rhs.len)-1]) l.len=max(this->len,rhs.len)+1; else l.len=max(this->len,rhs.len); memcpy(l.mem,buf,memLen); return l; } LLint& operator=(int n) { len=0; while(n) { mem[memLen-1-len++]=n%10+'0'; n/=10; } return *this; } void print() { for(int i=len-1;i>=0;i--) fout<<mem[memLen-i-1]; } }; LLint cnt[5002]; int main() { int m=1; fin>>N; for(int i=1;i<=N;++i) fin>>price[i]; price[N+1]=0; for(int i=1;i<=N+1;++i) for(int j=i+1;j<=N+1;++j) { if(price[i]==price[j]) { nextp[i]=j; break; } } int maxlen[5002]; for(int i=1;i<=N+1;++i) maxlen[i]=1,cnt[i]=1; for(int i=2;i<=N+1;i++) { for(int j=1;j<i;j++) { if(nextp[j]&&nextp[j]<i) continue; if(price[i]<price[j]) { if(maxlen[i]==maxlen[j]+1) cnt[i]=cnt[i]+cnt[j]; else if(maxlen[i]<maxlen[j]+1) maxlen[i]=maxlen[j]+1,cnt[i]=cnt[j]; } } } fout<<maxlen[N+1]-1<<" "; cnt[N+1].print(); fout<<endl; return 0; }