牛客小白月赛47

比赛链接

牛客小白月赛47

D.造桥

题目描述

今天是愉快的周末,牛可乐和牛妹在一起玩游戏。牛妹给了牛可乐 n 个造桥的零件,每个零件以字符串的形式给出,每个字符串两端的字符是零件的接口,两个零件可以通过连接不同端的接口(一个零件的左端只能连接另一个零件的右端,右端则只能连接左端)得到一个更长的零件,新零件的长度是原零件的长度之和。
牛妹规定,零件不能翻转,且零件左边的接口只能由该零件左边的零件去连接(这意味着,应该按顺序选取零件),右端同理。
牛可乐想得到牛妹的赞许,因此他要想用牛妹给的零件拼接一个尽可能长的桥梁,你能帮帮他吗?

输入描述:

第一行一个整数 T, 代表案例数。
对于每一个样例: 第一行一个数 n, 表示字符串的个数。
接下来有 n 行, 每行一个字符串, 每个字符串的长度 2

0<T100
所有案例的字符串长度的和不超过 2e5
保证所有字符均为小写字符。

输出描述:

n 个字符串能拼接的最大字符串长度。

示例1

输入

1 6 ab baabc bb ba ba ad

输出

8

说明

按顺序依次拼接:1356号字符串。

解题思路

思维,dp

相当于将每个字符串的第一个字符向最后一个字符连边,权值为字符串长度,从左到右求最大权值之和

  • 状态表示:f[i] 表示以 i 结尾的最大权值

  • 状态计算:f[r]=max(f[r],(int)s.size()+f[l]),其中 l,r 分别为字符串 s 的前后字符
    分析:当前字符串是否对于 r 结尾的最大权值之和有贡献

代码

// %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=27; int f[N],t,n; int main() { for(cin>>t;t;t--) { memset(f,0,sizeof f); cin>>n; for(int i=1;i<=n;i++) { string s; cin>>s; f[s.back()-'a']=max(f[s.back()-'a'],(int)s.size()+f[s[0]-'a']); } int res=0; for(int i=0;i<26;i++)res=max(res,f[i]); cout<<res<<'\n'; } return 0; }

E.牛牛的方格图

题目描述

牛牛: “你喜欢玩数独吗? 。
牛牛有一个 nm 的方格图,每个格子都有自己的颜色,第 i 行第 j 列格子上的颜色记为 col(i,j)
对于任意两个不同位置的颜色相同的点,我们认为其覆盖了一个以它们为对角线上顶点的矩形中的所有点。
严格来说,一个点 P(ip,jp) 被覆盖,当且仅当存在两个点 A(ia,ja)B(ib,jb) 使得以下四个条件都成立:
1: col(ia,ja)=col(ib,jb)
2: iaibjajb
3: min(ia,ib)ipmax(ia,ib)
4: min(ja,jb)jpmax(ja,jb)
现在牛牛想知道这张方格图中有多少个顶点尚末被覆盖。

输入描述:

第一行输入两个数 n,m 代表方格图的行数和列数。
接下来 n 行每行 m 个数描述了方格图中每个格子上的颜色。
0<n,m1e3;0<col(i,j)1e6

输出描述:

输出一行一个整数代表答案。

示例1

输入

3 4 1 3 3 4 2 3 1 4 6 3 3 4

输出

1

说明

6所在方格未被覆盖。

解题思路

思维,二维前缀和

先将同一个颜色的位置提取出来,如果一个颜色出现的位置大于等于 2,则求出覆盖所有点的最小矩形,即找出最大和最小的横纵坐标,设定一个数组 ne[i][j],表示位于 (i,j) 连续覆盖的最左边的纵坐标,每次标记时可利用此数组快速标记未标记的位置,当然,也可以利用二维前缀和做标记

  • 时间复杂度:O(100000+nm)

代码

// Problem: 牛牛的方格图 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11224/E // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e6+6,M=1005; int n,m,x,ne[M][M]; vector<PII> c[N]; bool v[M][M]; int main() { read(n),read(m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++)read(x),c[x].pb({i,j}); } for(int i=0;i<=1e6;i++) { if(c[i].size()>1) { int x1=M,y1=M,x2=0,y2=0; for(auto t:c[i]) { x1=min(x1,t.fi); y1=min(y1,t.se); x2=max(x2,t.fi); y2=max(y2,t.se); } for(int j=x1;j<=x2;j++) for(int k=y1;k<=y2;k++) { if(v[j][k])k=ne[j][k]; else { ne[j][k]=y2; v[j][k]=1; } } } } int res=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)res+=!v[i][j]; printf("%d",res); return 0; }
  • 前缀和
// Problem: 牛牛的方格图 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11224/E // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e6+6,M=1005; int n,m,x,s[M][M]; vector<PII> c[N]; bool v[M][M]; int main() { read(n),read(m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++)read(x),c[x].pb({i,j}); } for(int i=0;i<=1e6;i++) { if(c[i].size()>1) { int x1=M,y1=M,x2=0,y2=0; for(auto t:c[i]) { x1=min(x1,t.fi); y1=min(y1,t.se); x2=max(x2,t.fi); y2=max(y2,t.se); } s[x1][y1]++; s[x1][y2+1]--; s[x2+1][y1]--; s[x2+1][y2+1]++; } } int res=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)s[i][j]+=s[i][j-1]+s[i-1][j]-s[i-1][j-1],res+=!s[i][j]; printf("%d",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16120122.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示