首页 > 代码库 > CodeForces743E. Vladik and cards 二分+装压dp
CodeForces743E. Vladik and cards 二分+装压dp
这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有也不选,而且最后一个区间的第一个数一定可以使这个数区间对应的数,那么我们只要在某个位置上不选或选就可以啦,这we很容易想到2n的验根但是这样还不如打暴力,这时我们发现这个dfs是低效的他会很多进入等效状态这样的话我们就可以记忆化搜索了,那么何妨递推,由于我们知道f[pos][mask]中只要pos(位置),mask(二进制代表是否选过)确定那么就要他的最大值就行了,而状态转移分两种一是前面len或len+1,或前一个状态,那么只要每一个状态是最大值,那么我们就从前面推到最后就找到了,这样的话我们可以正向推来代替反向吸收,因为如果只有那样吸收也就只有那样推.
千万不要忘了0的特判以及状态转移的完全性.
时间复杂度o(8*log2n*28*n)
#include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 1001 using namespace std; int f[MAXN][(1<<8)+10]; int n,a[MAXN],full=(1<<8)-1; bool had[10]; vector<int>pos[10]; inline void pre() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); had[a[i]]=1; pos[a[i]].push_back(i); } } inline int Max(int x,int y) { return x>y?x:y; } inline int get(int p,int len) { int now=lower_bound(pos[a[p]].begin(),pos[a[p]].end(),p)-pos[a[p]].begin(); int ans=now+len-1; if(pos[a[p]].size()-1<ans)return -1; return pos[a[p]][ans]; } int judge(int len) { memset(f,0,sizeof(f)); for(int i=0;i<n;i++) { int to=get(i+1,len); if(to!=-1)f[to][(1<<(a[i+1]-1))]=Max(f[i][0]+len,f[to][(1<<(a[i+1]-1))]); to=get(i+1,len+1); if(to!=-1)f[to][(1<<(a[i+1]-1))]=Max(f[i][0]+len+1,f[to][(1<<(a[i+1]-1))]); for(int j=1;j<full;j++) if(f[i][j]) { f[i+1][j]=Max(f[i+1][j],f[i][j]); if(j&(1<<(a[i+1]-1)))continue; to=get(i+1,len); if(to!=-1)f[to][j|(1<<(a[i+1]-1))]=Max(f[i][j]+len,f[to][j|(1<<(a[i+1]-1))]); to=get(i+1,len+1); if(to!=-1)f[to][j|(1<<(a[i+1]-1))]=Max(f[i][j]+len+1,f[to][j|(1<<(a[i+1]-1))]); } f[i+1][full]=Max(f[i+1][full],f[i][full]); } return f[n][full]; } void work() { int ans=0,l=1,r=n>>3; for(int i=1;i<=8;i++) if(had[i])ans++; while(l<=r) { int mid=(l+r)>>1,x=judge(mid); ans=Max(x,ans); if(x) l=mid+1; else r=mid-1; } printf("%d",ans); } int main() { pre(); work(); return 0; }
CodeForces743E. Vladik and cards 二分+装压dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。