ABC370 Review

ABC 370 Review

A

模拟题,过

B

模拟题,过

C

很明显的贪心思路是把需要更改的字母分为两类:改大和改小。

首先我们要明确的是要让输出的串尽量拥有小的字典序,且字典序比较的第一关键字是位置,第二是长度

所以对于改小的部分,改的位置越靠前我们就放在越前面操作;

对于改大的部分,改的位置越靠前我们反而放在越后面操作;

这样排序下来就会是最优的。

D

考试的时候打了一个链表发现假了,根本无法维护现有的。

想起之前做过一道 ECFinal 的题也是通过 set 来维护同一行和同一列的关系,以后就要记性了。

简单来说就是通过二分查找(lower_bound)来快速地确定应该修改的位置。

以前的知识

set<int> s;
s.size();
s.count(int val);
s.lower_bound(int val);
s.erase(auto it/int val);

新学到的知识

vector<set<int>> s(n);可以预先声明大小
auto erase = [&](int x, int y)
{
h[x].erase(y);
l[y].erase(x);
};
可以创建闭包在主函数使用临时函数 用 erase(x,y) 的格式调用
prev(it) 可以查找当前迭代器的上一个位置的迭代器(begin()小心越界)

其他都没有什么需要注意的地方了

更优秀的解法

运用 set 来维护的时间代价是 O(logn) 的,实际上还有一种更加优秀的实现可以在接近 O(1) 的时间内完成。

想起来之前 2022绵阳CCPC 有一道水题也是给定 n 个人,然后会有干掉某个人的操作,需要你找到某个人右边最近的活人,当时用链表维护的,倒也没什么问题,因为只会查询活人。

但是这道题中被摧毁的点仍有可能在以后被查询到,所以链表就不适用了。

但有一种普适的算法就是 并查集 + 路径压缩,因为是变种并查集,所以维护的内容就不再是从属关系,所以查询函数要有小小的改动,注意要同时维护一个 vis 数组来记录有没有被摧毁,在并查集查询的时候照常路径压缩并且在 碰到 vis==1 的点的时候就返回。

注意这个题需要维护四个方向上的并查集,还要判断有没有出界,部分代码如下:

int fa_l[N],fa_r[N],fa_u[N],fa_d[N];
inline bool check(int x,int y)
{
return 1<=x&&x<=n&&1<=y&&y<=m;
}
inline int get_l(int x,int y)
{
if(!check(x,y))return -1;
if(!vis[x][y])return y;
return fa_l[y]=get_l(x,fa_l[y]);
}

E

连续区间划分问题

很明显的可以写出一个 O(n2) 的暴力 dp

for(int i=1;i<=n;++i)
{
if(sum[i]!=k)dp[i]=1;
for(int j=1;j<i;++i)
{
if(sum[i]-sum[j]!=k)dp[i]+=dp[j];
}
}

这样做必定会超时,那么想办法把第二维度优化掉。

我们在对当前的 dp[i] 进行计算的时候,相当于会把之前所有的 dp 值都累加进去,然后减去满足 sum[i]sum[j]==kdp[j]

考虑到每个 dp[i] 值在被计算之后就不会被再次更改,其位置对应的 sum[i] 也是固定的。

可以将其试做一个二元组 (sum[x],dp[x]) ,我们统计所有 dp 的和,再减去对于当前位置 i 不符合情况的,也就是满足 sum[x]==sum[i]k 的所有 dp[x] 。那么只需要开一个 map 来建立 sumdp 的关系就行,代码如下。

中间那段注释掉的 set 我也不知道为什么会有一个点 wa 掉,虽然但是肯定能被卡 TLE

posted @   Hanggoash  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
动态线条
动态线条end
点击右上角即可分享
微信分享提示