隐藏页面特效

Codeforces Round 910 (Div. 2)

1|0Preface


这场其实挺早之前就写完代码了,但一直没时间写博客(玩云顶新赛季玩的)

感觉F其实不难但为什么就是想不出来呢,感觉后面的题就是很难突破的说


2|0A. Milica and String


分类讨论+枚举即可

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=105; int t,n,k,sfx[N]; char s[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d%d%s",&n,&k,s+1),sfx[n+1]=0,i=n;i>=1;--i) sfx[i]=sfx[i+1]+(s[i]=='B'); if (sfx[1]==k) { puts("0"); continue; } puts("1"); if (sfx[1]<k) { for (i=1;i<=n;++i) if (i+sfx[i+1]==k) { printf("%d B\n",i); break; } } else { for (i=1;i<=n;++i) if (sfx[i+1]==k) { printf("%d A\n",i); break; } } } return 0; }

3|0B. Milena and Admirer


从后往前贪心地确定,在优先满足当前分裂次数最少的前提下,尽可能最大化分裂后最靠前的数

稍微推一下式子会发现,设当前数为x,下一个数的限制是y,则ans+=xy1,y=xxy

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=200005; int t,n,a[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]); LL ans=0; int lst=a[n]; for (i=n-1;i>=1;--i) ans+=(a[i]+lst-1)/lst-1,lst=a[i]/((a[i]+lst-1)/lst); printf("%lld\n",ans); } return 0; }

4|0C. Colorful Grid


小清新构造题,令s=n1+m1,先判掉s>k的无解情况,同时发现若ks是奇数也显然无解

那么剩下的就是根据ks4取模后的结果来分类讨论了,我们可以用如下的方式来构造前3×3的边

这样我们从(1,1)(3,3)后可以走出任意一条长4m/4m+2的合法路径,然后再从(3,3)走到(n,m)即可

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=20; int t,n,m,k,h[N][N],l[N][N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i,j; scanf("%d%d%d",&n,&m,&k); int s=n-1+m-1; if (s>k||(k-s)%2==1) { puts("NO"); continue; } for (i=1;i<=n;++i) for (j=1;j<m;++j) h[i][j]=1; for (i=1;i<n;++i) for (j=1;j<=m;++j) l[i][j]=1; h[1][1]=h[1][2]=h[2][1]=h[2][2]=l[2][2]=l[2][3]=1; l[1][1]=l[1][2]=l[1][3]=h[3][2]=0; int lst=(k-s)%4==2?1:0; puts("YES"); for (i=3;i<n;++i) lst^=1,l[i][3]=lst; for (j=3;j<m;++j) lst^=1,h[n][j]=lst; for (i=1;i<=n;++i) for (j=1;j<m;++j) printf("%c%c",h[i][j]?'R':'B'," \n"[j==m-1]); for (i=1;i<n;++i) for (j=1;j<=m;++j) printf("%c%c",l[i][j]?'R':'B'," \n"[j==m]); } return 0; }

5|0D. Absolute Beauty


要推清楚各种情况的话需要的精力比较多,后面实现就很简单了

这里给出一种解决绝对值问题的通用思路,即分类讨论所有项的符号,最后统一取max

列出所有情况后会发现可能让答案变大的情形只有当选中(i,j),满足max(ai,bi)<min(aj,bj),或者max(aj,bj)<min(ai,bi)的情形

以第一种情况为例,直接扫一遍维护max(ai,bi)的最小值即可,总复杂度O(n)

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=200005; int t,n,a[N],b[N]; inline int solve(void) { int mi=1e9,ret=0; for (RI i=1;i<=n;++i) ret=max(ret,min(a[i],b[i])-mi),mi=min(mi,max(a[i],b[i])); return ret; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; LL sum=0; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]); for (i=1;i<=n;++i) scanf("%d",&b[i]),sum+=abs(a[i]-b[i]); int dlt=solve(); reverse(a+1,a+n+1); reverse(b+1,b+n+1); dlt=max(dlt,solve()); printf("%lld\n",sum+2LL*dlt); } return 0; }

6|0E. Sofia and Strings


想到关键就很简单的一个题

考虑从左到右扫描t中的每个字符c,当我们要在s中找一个与它相同的字符匹配时,显然找最靠前的是最优的

然后考虑对于找到的位置之前的其它字符c,如果c<c就必须被删掉,否则可以把它移动到后面去下次再用

26deque模拟上述过程即可,总复杂度O(26×n)

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=200005; int t,n,m; char a[N],b[N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i,j; scanf("%d%d%s%s",&n,&m,a+1,b+1); deque <int> dq[26]; for (i=1;i<=n;++i) dq[a[i]-'a'].push_back(i); bool flag=1; for (i=1;i<=m;++i) { if (dq[b[i]-'a'].empty()) { flag=0; break; } int pos=dq[b[i]-'a'].front(); dq[b[i]-'a'].pop_front(); for (j=0;j<b[i]-'a';++j) while (!dq[j].empty()&&dq[j].front()<pos) dq[j].pop_front(); } puts(flag?"YES":"NO"); } return 0; }

7|0F. Vova Escapes the Matrix


其实一点不难的一个题,但为什么我就是想不到呢

首先对于Type1的情形,直接把所有空位填了即可;对于Type2的话就找到起点到出口的最短路,保留这上面的所有点即可

考虑Type3的情形要怎么处理,显然最后让起点刚好有2种出走方式是最优的

那么对于这种两条路径的问题,一般分析之后都会有相交的性质,这题也不例外

我们发现最后答案的构成一定形如:先从起点走到某个点,然后从该点恰好存在两条通向不同出口的路径

考虑怎么维护答案,难点在于维护后面那个东西,不过我们可以通过魔改BFS来求出到每个点的最近出口和次近出口

最后从起点出发再BFS一遍即可求出前者,最后枚举中转点即可

总复杂度O(n×m)

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=1005,INF=5e8,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1}; struct ifo { int x,y,d; inline ifo(CI X=-1,CI Y=-1,CI D=INF) { x=X; y=Y; d=D; } }f[N][N][2]; int t,n,m,sx,sy,f3[N][N]; char a[N][N]; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) for (scanf("%s",a[i]+1),j=1;j<=m;++j) if (a[i][j]=='V') sx=i,sy=j; for (i=1;i<=n;++i) for (j=1;j<=m;++j) f[i][j][0]=f[i][j][1]=ifo(),f3[i][j]=INF; queue <ifo> q; for (i=1;i<=n;++i) for (j=1;j<=m;++j) if ((i==1||i==n||j==1||j==m)&&a[i][j]!='#') f[i][j][0]=ifo(i,j,0),q.push(ifo(i,j,0)); int all=0; for (i=1;i<=n;++i) for (j=1;j<=m;++j) all+=a[i][j]=='.'; while (!q.empty()) { auto [x,y,tp]=q.front(); q.pop(); for (i=0;i<4;++i) { int nx=x+dx[i],ny=y+dy[i]; if (nx<1||nx>n||ny<1||ny>m||a[nx][ny]=='#') continue; if (f[nx][ny][0].d==INF) f[nx][ny][0]=f[x][y][tp],++f[nx][ny][0].d,q.push(ifo(nx,ny,0)); else if ((f[nx][ny][0].x!=f[x][y][tp].x||f[nx][ny][0].y!=f[x][y][tp].y)&&f[nx][ny][1].d==INF) f[nx][ny][1]=f[x][y][tp],++f[nx][ny][1].d,q.push(ifo(nx,ny,1)); } } if (f[sx][sy][0].d==INF) { printf("%d\n",all); continue; } if (f[sx][sy][1].d==INF) { printf("%d\n",all-f[sx][sy][0].d); continue; } q.push(ifo(sx,sy,f3[sx][sy]=0)); while (!q.empty()) { auto [x,y,d]=q.front(); q.pop(); for (i=0;i<4;++i) { int nx=x+dx[i],ny=y+dy[i]; if (nx<1||nx>n||ny<1||ny>m||a[nx][ny]=='#') continue; if (f3[nx][ny]==INF) q.push(ifo(nx,ny,f3[nx][ny]=d+1)); } } int ret=INF; for (i=1;i<=n;++i) for (j=1;j<=m;++j) ret=min(ret,f3[i][j]+f[i][j][0].d+f[i][j][1].d); printf("%d\n",all-ret); } return 0; }

8|0Postscript


感觉好久没有按时打CF了,看来是越来越怠惰了呢


__EOF__

本文作者hl666
本文链接https://www.cnblogs.com/cjjsb/p/17853195.html
关于博主:复活的ACM新生,目前爱好仅剩Gal/HBR/雀魂/单机/OSU
版权声明:转载请注明出处
声援博主:欢迎加QQ:2649020702来DD我
posted @   空気力学の詩  阅读(87)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示