AtCoder Beginner Contest 379 题解
AtCoder Beginner Contest 379
Rated:
-
A - Cyclic
简单模拟。
-
B - Strawberries
字符串模拟,
substr
函数秒了 -
C - Repeating
中等模拟。
思路:判断是否合法很简单,重点在计算花费。
假设我们是 号点有 个棋子,然后移动到每个点上,显然花费为
但是现在棋子不在 好点上,如果有一个 这个地方有 个棋子,那么就会省去 的花费。
接下来排序,简单模拟即可。 -
D - Home Garden
priority_queue + lazy_tag
-
E - Sum of All Substrings
拆贡献法,第
个数的数为 ,那么它左边选择的值会增加 种情况,而右边对答案产生 的贡献,
第 位的总花费就是 相当于给高精度的数 位加上
差分处理,再处理一下进位即可点击查看代码
#include<bits/stdc++.h> using namespace std; int n; long long ans[300001],c[200001]; char s[200001]; bool st; int main(){ scanf("%d%s",&n,s + 1); for(int i = 1;i <= n;i ++){ c[i] = i * (s[i] - '0'); } for(int i = n;i;i --){ ans[i] = ans[i + 1] + c[n - i + 1];//差分 } for(int i = 1;i < 300000;i ++){//进位 ans[i + 1] += ans[i] / 10; ans[i] = ans[i] % 10; } for(int i = 300000;i;i --){ if(ans[i]){//去除前导零 st = true; } if(st){ printf("%lld",ans[i]); } } return 0; }
-
F - Buildings 2
性质:对于一对
,在 处能看到的位置大于 的楼房,在 处一定也能看到;在 处能看到的楼房,在 处不一定能看到。因此,
都能看到的楼房一定是 能看到的位置大于 处的所有楼房。将询问离线,挂在
处。从序列最后倒着做一个单调栈,存着在当前点能够看到的楼房编号。那么在
处,对于所有以 为左端点的询问点对 ,能看到的楼房个数就是当前单调栈中位置大于 的楼房个数,可以通过在单调栈上二分查找得到。最后按询问顺序输出答案即可。
时间复杂度
。点击查看代码
#include <bits/stdc++.h> using namespace std; typedef pair <int, int> pii; const int N = 1e6 + 10; int n, Q, a[N]; int st[N], tot, ans[N]; vector <pii> query[N]; signed main () { ios::sync_with_stdio (false); cin.tie (0); cout.tie (0); cin >> n >> Q; for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1, l, r; i <= Q; ++i) cin >> l >> r, query[l].emplace_back (r, i); for (int i = n; i; --i) { for (auto [j, id] : query[i]) { int l = 1, r = tot; while (l < r) { int mid = (l + r + 1) >> 1; if (st[mid] > j) l = mid; else r = mid - 1; } if (st[l] <= j) ans[id] = 0; // 单调栈中不存在位置大于 j 的点 else ans[id] = l; } while (tot && a[st[tot]] < a[i]) --tot; st[++tot] = i; } for (int i = 1; i <= Q; ++i) cout << ans[i] << endl; return 0; }
-
G - Count Grid 3-coloring
注意数据范围
,那么对于一组数据, ,这启发使用状压DP。选择行数或列数的较小值来进行状态压缩。
设
表示扫到第 行,且当前行的状态为 的方案数。如果 和 不矛盾,我们使- 我们先预处理出每一行可以填什么(存到 vector 里)。
- 转移:枚举上一行的每一个状态,然后在枚举这一行的每一个状态。
- 初始值:
- 答案:
显然,滚动数组优化。
时间复杂度:
数组值全为 ,那么情况数即为 ( )。 ,但远远不会达到这个,有很多剪枝优化。
点击查看代码
#include <bits/stdc++.h> using namespace std; #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) #define ROF(i, a, b) for (int i = (a); i >= (b); --i) #define DEBUG(x) cerr << #x << " = " << x << endl #define ll long long typedef pair <int, int> PII; typedef unsigned int uint; typedef unsigned long long ull; #define i128 __int128 #define fi first #define se second mt19937 rnd(chrono::system_clock::now().time_since_epoch().count()); #define ClockA clock_t start, end; start = clock() #define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl; //#define int long long inline int rd(){ int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9'){ if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } #define rd rd() void wt(int x){ if (x < 0) putchar('-'), x = -x; if (x > 9) wt(x / 10); putchar(x % 10 + '0'); return; } void wt(char x){ putchar(x); } void wt(int x, char k){ wt(x),putchar(k); } namespace Star_F{ const int N = 205, M = 5000000, MOD = 998244353; int n,m; char s[N][N]; int a[N][N], b[N], u; vector<int> vec[N]; void dfs(int t){ if(t>m){ int nw=0; for(int i=1;i<=m;i++) nw=nw*3+b[i]; vec[u].push_back(nw); return; } if(a[u][t]!=-1 && a[u][t]!=b[t-1]){ b[t]=a[u][t]; dfs(t+1); } else if(a[u][t]==-1){ if(b[t-1]!=0) b[t]=0, dfs(t+1); if(b[t-1]!=1) b[t]=1, dfs(t+1); if(b[t-1]!=2) b[t]=2, dfs(t+1); } } int sm,sum[N]; long long f[2][M]; void dfs2(int t){ if(t>m){ int nw=0; for(int i=1;i<=m;i++) nw=nw*3+b[i]; f[u&1][nw]=(f[u&1][nw]+f[(u&1)^1][sm])%MOD; return; } if(b[t-1]!=0 && sum[t]!=0) b[t]=0, dfs2(t+1); if(b[t-1]!=1 && sum[t]!=1) b[t]=1, dfs2(t+1); if(b[t-1]!=2 && sum[t]!=2) b[t]=2, dfs2(t+1); } void Main(){ cin >> n >> m; memset(a,-1,sizeof(a)); for(int i=1;i<=n;i++){ cin >> s[i] + 1; for(int j=1;j<=m;j++){ if(s[i][j]=='1') a[i][j]=0; if(s[i][j]=='2') a[i][j]=1; if(s[i][j]=='3') a[i][j]=2; } } if(n<m){ //swap for(int i=1;i<=m;i++) for(int j=1;j<i;j++) swap(a[i][j],a[j][i]); swap(n,m); } for(int i=1;i<=n;i++){ u=i,b[0]=-1,dfs(1); } for(auto i:vec[1]) f[1][i]=1; //初始化 for(int i=2;i<=n;i++){ u=i; for(int j:vec[i-1]){ sm=j; for(int k=m;k>=1;k--) sum[k]=sm%3,sm/=3; sm=j; b[0]=-1; dfs2(1); } memset(f[(i&1)^1],0,sizeof(f[(i&1)^1])); } long long ans=0; for(auto i:vec[n]) ans=(ans+f[n&1][i])%MOD; cout << ans << endl; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); ClockA; int T=1; // T=rd; while(T--) Star_F::Main(); // ClockB; return 0; }
分类:
AtCoder比赛题解合集
标签:
题解
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!