传送门

文章目录

  • 题意:
  • 思路:

题意:

给你一个串,只包含前kkk个字母和???,定义fif_ifi​表示第iii个字母在串中出现的最长连续长度,你现在需要将???替换为前kkk个字母,使得mini=0k−1fimin_{i=0}^{k-1}f_imini=0k−1​fi​尽可能大。
n≤2e5,k≤17n\le2e5,k\le17n≤2e5,k≤17

思路:

让最小值尽可能大,我们可以考虑二分一个最小长度,让后考虑怎么检查答案呢?
假设二分的长度为midmidmid,可以发现问号拿出来之后一种有效方案每个连续段都涂一个色,所以如果我们能确定填字母的顺序,那么就可以从头扫这个串,让后贪心的将问号变成当前要变成的字母,当然过程中要算上非问号的贡献,一直到这个字母的长度=mid=mid=mid的时候停止,进行下一个要填的字母。
那么现在问题就变成了如何确定填字母的顺序,有个显然的方法就是k!k!k!枚举,显然过不去 。
考虑状压dpdpdp,为什么状压dpdpdp是可以确定顺序的呢?考虑以下代码:

 for(int i=0;i<1<<k;i++) {for(int j=0;j<k;j++) {if(i>>j&1) continue;int state=i|(1<<j);dp[state]=min(dp[state],f[j][dp[i]]);}}

由于我们不需要知道之前的数是怎么填的,只需要知道填完某几个数之后填了前几个字母,所以定义dp[i]dp[i]dp[i]表示填完了状态iii之后最少用到了前dp[i]−1dp[i]-1dp[i]−1个字母。之后就可以枚举状态了,其中jjj就是当前要填的数,由于state>istate>istate>i,所以从小到大枚举状态不会漏掉状态。
既然目前确定了顺序且知道了从哪里开始填,如何确定当前要填的数从当前位置最近需要到那个位置才能使得其连续的长度≥mid\ge mid≥mid呢?由于状压dpdpdp复杂度已经达到了2kk2^kk2kk,还有二分的复杂度,显然不能在里面暴力求,所以考虑预处理。
定义f[i][j]f[i][j]f[i][j]表示第iii个字母从jjj开始最近到那个位置才能满足条件,这个经典的倒着处理,注意一下边界就好啦。
复杂度O(nklogn+2kklogn)O(nklogn+2^kklogn)O(nklogn+2kklogn)

// Problem: E. Stringforces
// Contest: Codeforces - Educational Codeforces Round 111 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1550/problem/E
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,k;
char s[N];
int f[26][N],dp[1<<17];bool check(int len) {for(int i=0;i<k;i++) {f[i][n+1]=f[i][n+2]=n+2;int now=0;for(int j=n;j>=1;j--) {if(s[j]=='?'||s[j]=='a'+i) now++;else now=0;now>=len? f[i][j]=j+len:f[i][j]=f[i][j+1];}}for(int i=0;i<1<<k;i++) dp[i]=n+2;dp[0]=1;for(int i=0;i<1<<k;i++) {for(int j=0;j<k;j++) {if(i>>j&1) continue;int state=i|(1<<j);dp[state]=min(dp[state],f[j][dp[i]]);}}return dp[(1<<k)-1]<=n+1;
}int main()
{//  ios::sync_with_stdio(false);
//  cin.tie(0);cin>>n>>k>>(s+1);int l=0,r=n;while(l<r) {int mid=(l+r+1)>>1;if(check(mid)) l=mid;else r=mid-1; }printf("%d\n",l);return 0;
}
/**/

Educational Codeforces Round 111 (Rated for Div. 2) E. Stringforces 二分 + 状压dp相关推荐

  1. Educational Codeforces Round 111 (Rated for Div. 2) D. Excellent Arrays 组合数学

    传送门 文章目录 题意: 思路: 题意: 给你一个数组aia_iai​,定义一个数组是好的当且仅当对于所有iii都有ai!=ia_i!=iai​!=i.定义f(a)f(a)f(a)表示数组aaa中i& ...

  2. Educational Codeforces Round 111 (Rated for Div. 2)

    Educational Codeforces Round 111 (Rated for Div. 2) 题号 题目 知识点 A Find The Array B Maximum Cost Deleti ...

  3. Educational Codeforces Round 73 (Rated for Div. 2) Make The Fence Great Again dp + 结论

    传送门 文章目录 题意: 思路: 题意: 思路: 首先证明一个结论:一个数最多被加两次. 首先假设a[i]=a[i−1]a[i]=a[i-1]a[i]=a[i−1]或a[i]=a[i+1]a[i]=a ...

  4. Educational Codeforces Round 81 (Rated for Div. 2) E. Permutation Separation 线段树 + dp

    传送门 文章目录 题意: 思路: 题意: 给你一个打乱的排列,每个位置都各有一个价值,让你选择一个分界点,分成p1,p2,...,prp_1,p_2,...,p_rp1​,p2​,...,pr​和pr ...

  5. CodeForces - 1550E Stringforces(二分+状压dp)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串,只包含前 kkk 个小写字母以及通配符 ???,现在可以将通配符替换成任意的前 kkk 个字母中的一个.设 f[i]f[i]f[i] 为 ...

  6. Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Educational Codeforces Round 114 (Rated for Div. 2) ...

  7. Educational Codeforces Round 89 (Rated for Div. 2)(A, B, C, D)

    Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords 思路 题意非常简单,就是得到最多的物品嘛,我们假定a, ...

  8. Educational Codeforces Round 72 (Rated for Div. 2) D. Coloring Edges dfs树/拓扑找环

    传送门 文章目录 题意: 思路: 题意: 给你一张图,你需要给这个图的边染色,保证如果有环那么这个环内边的颜色不全相同,输出染色方案和用的颜色个数. n,m≤5e3n,m\le5e3n,m≤5e3 思 ...

  9. Educational Codeforces Round 73 (Rated for Div. 2) E. Game With String 思维博弈 好题(2500)

    传送门 文章目录 题意: 思路: 题意: 思路: 我们将每一段...拿出来看成若干段,将其分成以下四种情况: (1)len<b(1)len<b(1)len<b (2)b≤len< ...

最新文章

  1. 如何查看别人公众号自定义菜单的功能_如何注册自己的个人公众号?手把手教您开启自媒体赚钱之路?...
  2. 嵌入式软件设计第8次实验报告-140201235-陈宇
  3. CCNP之IS-IS实验
  4. 深度学习核心技术精讲100篇(五十四)-阿里文娱多模态视频分类算法中的特征改进
  5. 每天一个Linux命令之ps-查看系统进程信息
  6. python 类的特殊成员(属性和方法)
  7. 使用 ADO.NET 的 NextResult 方法取得多个 Result Set
  8. C# 6.0 (C# vNext) 的新功能:Expression Bodied Functions and Properties
  9. 【报告分享】2022年快手新市井商业内循环营销通案:让企业经营走向确定性增长.pdf(附下载链接)...
  10. python中直方图bins是什么意思_Python 中下划线的 5 种含义都是什么?
  11. Atitit gc 垃圾回收原理与概论and 自动资源管理的艺术 v2 1. 为什么需要gc 1 1.1. 如果长期不被释放,可能导致OOM。 1 1.2. ,目的在于防止由程序猿引入的人为的内存
  12. UI自动化测试(APP测试)
  13. PPT里面如何插入斜体文字
  14. python rsa模块学习笔记
  15. 我的android足迹
  16. 【题解】Cutting Woods
  17. 使用pyfinance进行证券收益分析!金融界的一大帮手!
  18. 级数收敛与交换运算顺序
  19. blender合并物体后材质丢失问题的解决办法
  20. 再见,x 雷!这款 Github 全能下载工具,太强了!

热门文章

  1. wireshark-win64-3.4.0安装_这9类轴承的安装方法,你可都知道?有哪些需要注意的呢?...
  2. 06-广度优先搜索:图、队列
  3. 20以内究竟包不包括20?
  4. 如果这个世界都不按套路出牌将会变成怎么样。。。 | 今日最佳
  5. 老板啥都懂,还天天套路我?!
  6. java access dbq_Java-Access汇总
  7. android java 8_四个库,让你在 Android 中启用 Java 8 功能
  8. android动画送礼物,Android仿直播类app赠送礼物功能
  9. 2020邮箱账号密码大全_通知 | 复旦大学2020年春季学期研究生选课FAQ
  10. java导入导出excel_Java导入导出Excel工具 easyexcel