主页
搜索
最近更新
数据统计
申请密钥
批量保存
开发版网站(新前端)
系统公告
1
/
1
请查看完所有公告
题解:P5972 [PA2019] Desant
最后更新于 2025-08-27 19:17:22
作者
云浅知处
分类
题解
题解
P5972
复制 Markdown
查看原文
转到新前端
删除文章
更新内容
好像是我初二的时候提出的一个问题,当时 u 群有人说存在 $O(n^23^{n/3})$ 做法,昨天晚上突然会做了! 考虑从前往后 DP,暴力是记录 $S$ 表示目前选择的数的集合,这样状态数仍然是 $O(2^n)$ 级别。 但我们注意到,设 $i$ 后面的数分别为 $x_1,x_2,\cdots,x_k$,我们只关心 $[1,x_1),(x_1,x_2),\cdots,(x_k,n]$ 这些每一段中选了多少个数。于是状态数不会超过每段长度 $+1$ 的乘积,由柯西不等式可以知道一定在段长相同时取到最值,直接看成连续的情况来分析,简单求导可以得到最值在 $e^{n/e}$,由于问题是离散的于是最值大约是 $3^{n/3}$。 于是直接 DP 就可以了。时间复杂度是 $O(n^23^{n/3})$,使用 `map` 或许会被卡常,手写哈希表可以稳过。 ```cpp #include<bits/stdc++.h> #define ll long long #define mk make_pair #define fi first #define se second using namespace std; inline int read(){ int x=0,f=1;char c=getchar(); for(;(c<'0'||c>'9');c=getchar()){if(c=='-')f=-1;} for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15); return x*f; } const int N=41; const int M=(1<<22); const int P=47; int a[N],n; struct HashMap{ pair<int,ll>vals[M]; vector<int>havs; vector<int>act[M]; int head[M],nxt[M],tot; int size(){return tot;} void clear(){ for(int i=1;i<=tot;i++)nxt[i]=0,vector<int>().swap(act[i]); for(int i:havs)head[i]=0; vector<int>().swap(havs),tot=0; } void Ins(vector<int>&A,pair<int,ll>val){ int res=0; for(int x:A)res=(((res*P)+x+1)&(M-1)); int p=head[res]; if(!p)p=++tot,act[p]=A,vals[p]=val,havs.emplace_back(res),head[res]=p; else{ while(act[p]!=A&&p)p=nxt[p]; if(!p)p=++tot,act[p]=A,vals[p]=val,nxt[p]=head[res],head[res]=p; else{ if(vals[p].fi==val.fi)vals[p].se+=val.se; else if(vals[p].fi>val.fi)vals[p]=val; } } } }; HashMap f[2]; signed main(void){ n=read(); for(int i=1;i<=n;i++)a[i]=read(); int cur=0; vector<int>NaganoharaYoimiya(n+1,0); f[0].Ins(NaganoharaYoimiya,mk(0,1ll)); for(int i=1;i<=n;i++){ vector<int>x;f[cur^1].clear(); for(int j=i;j<=n;j++)x.emplace_back(a[j]); sort(x.begin(),x.end());int p=0; for(int j=0;j<x.size();j++)if(x[j]==a[i])p=j; for(int _=1;_<=f[cur].tot;_++){ auto A=f[cur].vals[_]; int w=A.fi;ll cc=A.se; int nw=0;for(int j=p+1;j<f[cur].act[_].size();j++)nw+=f[cur].act[_][j]; auto to=f[cur].act[_];int cnt=to[p]+to[p+1]; to.erase(to.begin()+p); to[p]=cnt,f[cur^1].Ins(to,mk(w,cc)); to[p]=cnt+1,f[cur^1].Ins(to,mk(w+nw,cc)); } cur^=1; } vector<pair<int,ll> >ans(n+1); for(int i=1;i<=f[cur].tot;i++){ auto vec=f[cur].act[i];auto A=f[cur].vals[i]; assert(vec.size()==1); int cnt=vec[0]; ans[cnt]=A; } for(int i=1;i<=n;i++)cout<<ans[i].fi<<" "<<ans[i].se<<endl; return 0; } ```
正在渲染内容...
点赞
20
收藏
0