CodeForces 718E Matvey’s Birthday

题目大意

◇题目传送门◆

今天与 CF 的连接怎么这么稳定???

给定一个长度为NNN的字符串sss,字符集为小写字母aaa到hhh,我们可以按照如下方式构造出一个无向图:

  • 若∣i−j∣≤1|i-j|\le 1∣i−j∣≤1,则在点iii和点jjj之间连一条长度为111的边;
  • 若si=sjs_i=s_jsi​=sj​,则在点iii和点jjj之间连一条长度为111的边。

若d(i,j)d(i,j)d(i,j)为i,ji,ji,j之间的最短路径,则定义这张图的直径为max⁡1≤i,j≤N,i≠j{d(i,j)}\max_{1\le i,j\le N,i\neq j}\{d(i,j)\}max1≤i,j≤N,i​=j​{d(i,j)}。

求这张图的直径和d(i,j)d(i,j)d(i,j)等于直径的点对数量。

分析

结论: d(i,j)d(i,j)d(i,j)是不会超过151515的。

证明: 我们可以发现,在从iii到jjj的最短路径上,一种字母一定不会出现超过两次。若出现了多于两次的字母,我们可以发现只需经过原来路径上的第一个和最后一个(因为它们直接有边相连)就可以使得路径变短。这样,由于最多只有888种字母,则最长的长度为2×8−1=152\times 8-1=152×8−1=15。

则我们考虑定义f(i,j)f(i,j)f(i,j)为从iii出发,到达某个颜色是jjj的位置的最短距离,这个可以用 BFS 做出来。这部分 比较简单 就不详细解释了。

考虑如何用f(i,j)f(i,j)f(i,j)来表示d(i,j)d(i,j)d(i,j):

  • 只经过第一种类型的边(即∣i−j∣≤1|i-j|\le 1∣i−j∣≤1时连上的边),这样这个距离就是∣i−j∣|i-j|∣i−j∣;
  • 经过第二种类型的边,我们可以考虑通过某个颜色为ccc中转点,这样这个距离就是f(i,c)+1+f(j,c)f(i,c)+1+f(j,c)f(i,c)+1+f(j,c)。

综上:

d(i,j)=min⁡(∣i−j∣,min⁡1≤c≤8{f(i,c)+f(j,c)+1})d(i,j)=\min(|i-j|,\min_{1\le c\le 8}\{f(i,c)+f(j,c)+1\}) d(i,j)=min(∣i−j∣,1≤c≤8min​{f(i,c)+f(j,c)+1})

这样一来我们就可以在O(N2)O(N^2)O(N2)的时间内求出d(i,j)d(i,j)d(i,j)。

但是NNN有10510^5105,我们不能够直接暴力。

考虑计算一个新的值g(i,j)g(i,j)g(i,j)表示从某个颜色为iii的节点到某个颜色为jjj的节点的最短距离,这个值可以在做 BFS 时顺带着算了。

对于∣i−j∣≤15|i-j|\le 15∣i−j∣≤15的情况,我们直接采用暴力。

但对于∣i−j∣>15|i-j|>15∣i−j∣>15时,我们可以发现,f(i,c)f(i,c)f(i,c)不是等于g(si,c)g(s_i,c)g(si​,c)就是等于g(si,c)+1g(s_i,c)+1g(si​,c)+1,又由于ccc只有最多888情况,所以我们可以将这个压成一个集合SSS,若SSS的第ccc位为000则表示f(i,c)=g(si,c)f(i,c)=g(s_i,c)f(i,c)=g(si​,c),反之就表示f(i,c)=g(si,c)+1f(i,c)=g(s_i,c)+1f(i,c)=g(si​,c)+1。

那么我们可以再用O(N222N)O(N^22^{2N})O(N222N)的复杂度来做一个预处理。设h(i,j,S1,S2)h(i,j,S_1,S_2)h(i,j,S1​,S2​)表示一个颜色为iii、状态为S1S_1S1​和另外一个颜色为jjj、状态为S2S_2S2​时的点的合并时的最小结果。

那么我们在统计答案时直接调用我们计算出来的hhh即可。

总时间复杂度为O(8N+83×22N+8N×2N)O(8N+8^3\times 2^{2N}+8N\times 2^N)O(8N+83×22N+8N×2N)。

参考代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;typedef long long ll;
const int Maxn = 100000;
const int Maxk = 8;int N;
char s[Maxn + 5];int f[Maxn + 5][Maxk + 5];
int g[Maxk + 5][Maxk + 5];
vector<int> p[Maxk + 5];void BFS(int col) {static bool vis[Maxn + Maxk + 5];memset(vis, false, sizeof vis);queue<int> q;for(int j = 0; j < (int)p[col].size(); j++)q.push(p[col][j]), vis[p[col][j]] = true, f[p[col][j]][col] = 0;g[col][col] = 0, vis[N + col] = true;while(!q.empty()) {int u = q.front();q.pop();if(u != 1 && !vis[u - 1]) {vis[u - 1] = true, q.push(u - 1);f[u - 1][col] = f[u][col] + 1;}if(u != N && !vis[u + 1]) {vis[u + 1] = true, q.push(u + 1);f[u + 1][col] = f[u][col] + 1;}if(vis[N + (int)s[u] - 'a' + 1]) continue;vis[N + (int)s[u] - 'a' + 1] = true;g[s[u] - 'a' + 1][col] = f[u][col];for(int i = 0; i < (int)p[s[u] - 'a' + 1].size(); i++) {int v = p[s[u] - 'a' + 1][i];if(vis[v]) continue;f[v][col] = f[u][col] + 1;vis[v] = true, q.push(v);}}
}int cnt[Maxk + 5][(1 << Maxk) + 5];
int dis[Maxk + 5][Maxk + 5][(1 << Maxk) + 5][(1 << Maxk) + 5];
int st[Maxn + 5];int main() {#ifdef LOACLfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifscanf("%d", &N);scanf("%s", s + 1);for(int i = 1; i <= N; i++)p[s[i] - 'a' + 1].push_back(i);memset(f, 0x3f, sizeof f);memset(g, 0x3f, sizeof g);for(int i = 1; i <= Maxk; i++)BFS(i);memset(dis, 0x3f, sizeof dis);for(int col1 = 1; col1 <= 8; col1++)for(int col2 = 1; col2 <= col1; col2++)for(int s1 = 0; s1 < (1 << 8); s1++)for(int s2 = 0; s2 < (1 << 8); s2++) {for(int col3 = 1; col3 <= 8; col3++)dis[col1][col2][s1][s2] = min(dis[col1][col2][s1][s2],g[col1][col3] + g[col2][col3] + ((s1 >> (col3 - 1)) & 1)+ ((s2 >> (col3 - 1)) & 1) + 1);dis[col2][col1][s2][s1] = dis[col1][col2][s1][s2];}int ans = 0;ll sum = 0;for(int i = 1; i <= N; i++) {for(int j = max(1, i - 15); j < i; j++) {int tmp = i - j;for(int col = 1; col <= 8; col++)tmp = min(tmp, f[i][col] + f[j][col] + 1);if(ans < tmp) ans = tmp, sum = 0;if(ans == tmp) sum++;}for(int col = 1; col <= 8; col++)st[i] |= (f[i][col] - g[s[i] - 'a' + 1][col]) << (col - 1);for(int col = 1; col <= 8; col++)for(int j = 0; j < (1 << 8); j++)if(cnt[col][j]) {int tmp = dis[col][s[i] - 'a' + 1][j][st[i]];if(ans < tmp) ans = tmp, sum = 0;if(ans == tmp) sum += cnt[col][j];}if(i > 15) cnt[s[i - 15] - 'a' + 1][st[i - 15]]++;}printf("%d %lld\n", ans, sum);return 0;
}

【CodeForces】【BFS】【状压】718E Matvey's Birthday相关推荐

  1. bfs+状压——朋也与光玉

    朋也与光玉 本来说好了再做一下之前没写起的题的,但是看到队友写了这道题手还是比较痒,于是就写了. ------------------------------------------ 题解: 这道题和 ...

  2. HDU 5025:Saving Tang Monk(BFS + 状压)

    http://acm.hdu.edu.cn/showproblem.php?pid=5025 Saving Tang Monk Problem Description <Journey to t ...

  3. Tunnels HDU - 4856 (bfs状压dp)

    Tunnels HDU - 4856 Bob is travelling in Xi'an. He finds many secret tunnels beneath the city. In his ...

  4. HDU-4856 Tunnels(BFS状压DP)

    Tunnels http://acm.hdu.edu.cn/showproblem.php?pid=4856 Time Limit: 3000/1500 MS (Java/Others)    Mem ...

  5. QDUOJ 来自xjy的签到题(bfs+状压dp)

    来自xjy的签到题 Description 爱丽丝冒险来到了红皇后一个n*n大小的花园,每个格子由'.'或'#'表示,'.'表示爱丽丝可以到达这个格子,'#'表示爱丽丝不能到达这个格子,爱丽丝每1分钟 ...

  6. CodeForces 11D(状压DP 求图中环的个数)

    Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no re ...

  7. hdu 4568 bfs + 状压dp

    //这题的数据是不是有问题... 不考虑宝藏一个也拿不到也能AC... 1 #include "bits/stdc++.h" 2 using namespace std; 3 co ...

  8. HDU - 1429 胜利大逃亡(续) (BFS+状压)

    题目链接 思路 因为新拿到一把钥匙所以相同位置可以重复走,一共10把钥匙二进制表示拿到的钥匙,判断下个位置是否可以走. #include <bits/stdc++.h> const int ...

  9. HDU 4856 Tunnels(BFS+状压DP)

    HDU 4856 Tunnels 题目链接 题意:给定一些管道.然后管道之间走是不用时间的,陆地上有障碍.陆地上走一步花费时间1,求遍历全部管道须要的最短时间.每一个管道仅仅能走一次 思路:先BFS预 ...

  10. HDU4856:Tunnels (BFS 状压dp)

    Bob is travelling in Xi'an. He finds many secret tunnels beneath the city. In his eyes, the city is ...

最新文章

  1. 转载:如何区分空间参考、坐标系统、投影、基准面和椭圆体?
  2. Linux中使用gcp拷贝报错:dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NotSupported:
  3. JavaScript学习笔记——对象知识点
  4. cxgrid按条件计算合计值
  5. java controller json_springMVC的controller层接收前端json数据
  6. 光骓者的荣耀(洛谷P5638题题解,弃坑Java拥抱C++)
  7. 通讯故障_PLC与变频器通讯故障处理实例
  8. 冲刺CCNA2.0(200-120)认证考试TK视频讲解
  9. enumerable java_ruby中的Enumerable的使用
  10. 【渝粤教育】国家开放大学2018年春季 0222-21T模拟电子电路 参考试题
  11. PowerPoint储存此文件时发生错误 出现错误的问题解决方法
  12. 7-15 福到了 c语言,7-54 福到了 (15 分)
  13. linux断电并重启命令,Linux基本操作:关机 重启
  14. Gitbook:无法加载文件C:\Users\Administrator\AppData\Roaming\npm\\gitbook.ps1因为在此系统上禁止运行脚本的解决方法
  15. 学生命科学要学计算机吗,生命科学属于什么门类 计算机科学与技术专业属于什么门类...
  16. 快速上手matlab(二)
  17. Eclipse 断点不生效原因之一 Tigger Point 断点右下角出现类似箭头
  18. 学生参加计算机比赛后的分析,湘南学院学生参加基本功大赛篮球比赛成绩分析和反思.doc...
  19. 高级转录组分析和R数据可视化技术研讨会(2023.2)
  20. 纳米二氧化硅修饰中孔ZSM-5沸石微球/含钆介孔二氧化硅海藻酸钠纳米微球

热门文章

  1. Unity3D离线版数字地球实现
  2. 超级无敌各种排序算法 一个代码解决<可以做后序模板>
  3. haproxy 客户端真实IP地址添加白名单
  4. Unity3D学习:飞碟游戏进化版
  5. UNOVO联永羲和开源项目
  6. 1.试用期个人工作总结(篇一)
  7. 修改WSL的Ubuntu环境下ls显示的文件夹文字颜色和背景色
  8. 腾讯课堂小白训练——仿百度登陆页面
  9. C# 关于Microsoft.Office.Interop.Word中app.Documents.Add/Open报错
  10. 【spark运行报错】