0%

题目大意

Mitty是一位勇敢的冒险者,正在探索一个被称为深渊的神秘地下洞穴系统。深渊由nn个平行垂直井和mm个水平隧道组成。每条隧道恰好连接两个相同深度的井。所有mm个隧道的深度各不相同,令人惊讶的是,每条隧道的中间都藏有一宝藏!

Mitty可以选择任意一个井开始。他从所选井的顶部向下移动,遵守以下规则:

  • 他只能向下移动,不允许向上移动。

  • 每当他遇到水平隧道时,必须立即进入,并将到达连接的井。

  • 一旦他进入水平隧道,就不能回头。

这些隧道中的宝藏有各种价值。Mitty想要尽可能多地收集宝藏。请帮助他计算从一个井开始时他可以收集到的最大总宝藏价值。

最大样例的示例图:

image

思路讲解

可以把两个值绑在一起,当然三个,四个也是可以的。

注意,由于必须移动,因此不能够去 max。

1
2
3
4
5
6
7
8
9
10
11
12
void Solve() {
ll N,M;
cin >> N >> M;
vector<ll> dp(N+2);
for (int i=1;i<=M;++i) {
ll u,v,w;
cin>>u>>v>>w;
tie(dp[u],dp[v])=(pair<ll,ll>){dp[v]+w,dp[u]+w};
}
ll ans=*max_element(all(dp));
cout<<ans<<"\n";
}

AC代码

AC
https://codeforces.com/gym/106084/submission/361088193

心路历程(WA,TLE,MLE……)

题目大意

两个字符串uuvv之间的编辑距离是将uu转换为vv的最小编辑操作次数。可以对字符串应用三种编辑操作:插入字符,删除字符,用不同字符替换某个字符。

例如,我们可以用四次替换将hello转换为world,因此编辑距离最多为44。您可以用两次替换和一次插入将wally转换为walter,因此编辑距离最多为33。计算两个字符串之间的编辑距离是一个众所周知的问题,有许多应用。

当前任务是计算一个字符串到最接近的回文串的编辑距离。回文串是从后往前读和从前往后读相同的字符串,例如madam。

hello到最接近回文串的编辑距离仅为22:我们可以用两次编辑操作将hello转换为ollo,或hllh,或elle。

编写一个程序,可以找到一个单词到最接近回文串的距离。

思路讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
auto dfs=[&](auto && self,ll l,ll r) -> ll {
if (r==l) {
return 0;
}
if (r-l==1) {
return s[l]!=s[r];
}
if (dp[l][r]!=INF) {
return dp[l][r];
}
dp[l][r]=min({self(self,l+1,r-1)+(s[l]!=s[r]), // 替换
self(self,l,r-1)+1, // 删除右侧(等价于左侧插入一个相同的抵消)
self(self,l+1,r)+1, // 删除左侧(等价于在右侧插入一个相同的)
});
return dp[l][r];
};

AC代码

AC
https://codeforces.com/gym/106084/submission/361098919

心路历程(WA,TLE,MLE……)

题目大意

Jerry和Tom正在一个有nn个顶点的有向图GG上玩一个游戏,顶点编号从11nn。对于每个顶点1u<n1 \le u < n,从uuu+1u+1有一条有向边。此外,还有mm条额外的有向边。第ii条额外边从uiu_iviv_i

GG具有以下特殊性质:不存在两条有向边(uivi)(u_i\to v_i)(ujvj)(u_j\to v_j)使得ui<uj<vi<vju_i < u_j < v_i < v_j

在游戏开始时,Jerry和Tom分别站在顶点xxyy上,其中xyx \ne y。游戏按照轮次进行。在每个轮次中,玩家根据以下规则行动,Jerry先行,然后是Tom:

  • Jerry 必须选择从他当前顶点出发的一条出边****并沿着它移动到终点。如果他当前顶点没有出边,则他保持原地

  • Tom 可以选择从他当前顶点出发的一条出边并沿着它移动到终点,或者选择不移动并保持原地。

如果在任何轮次结束时,Jerry和Tom在同一个顶点上(包括在顶点nn),游戏立即结束且Tom获胜。否则,如果Jerry最初在顶点nn,或在任何轮次结束时到达顶点nn,Jerry获胜。

注意,如果在一轮之后,Jerry和Tom都在顶点nn,则Tom获胜

在整个游戏过程中,两个玩家都知道对方的位置。

可以证明游戏会在有限轮次内结束。

对于一对整数1x,yn1 \le x,y \le nxyx \ne y,定义f(x,y)f(x,y)如下:

  • Jerry和Tom将进行一个游戏,其中Jerry从顶点xx开始,Tom从顶点yy开始。Tom想赢,但他也想最小化他实际移动的次数(即,他改变顶点的轮次数;原地不算移动)。假设双方都以最佳方式行动,如果Tom不能赢则令f(x,y)=0f(x,y)=0;否则,令f(x,y)f(x,y)为Tom强迫赢所需的最小移动次数。如果Tom在最佳游戏中获胜,Jerry仍会尽力最大化Tom必须移动的次数。

计算

1x,yn,xyf(x,y). \sum\limits_{1 \le x,y \le n, x \ne y}f(x,y).

思路讲解

我们梳理一下题意,并进行一下样例解释

image

题目不允许这样子的两条边存在。

image

在样例 2 中,贡献为 1 的两种情况。

如果说没有额外的边,那么答案就是 00。因为 Tom 在 Jerry 前面,反正肯定赢不了。Tom 在 Jerry 后面,守株待兔即可。可以发现,无论什么情况,根据定义,都是 00

我们现在这个问题还是回来,什么时候肯定不会有这个追及,有这个贡献?其实就是如果把额外边当作区间加法的话,Tom 在没有被任何区间覆盖的地方,肯定是不会有答案贡献的。

不过我们发现,这样子一种一种情况看,实在是太慢了。既然是博弈题目,那么Tom 和 Jerry 的最优策略是什么呢?就是每步都走最远的边

因此,我们不妨把 Tom 走的路径,以及 Jerry 走的路径绘画在一张图上(按照上面说的最优策略),这张图,其实是一颗树。

或者,换句话说,我们只保留每个点的最长出边(这样子就可以形成一颗树),较短的出边,我们直接删除(因为不符合)。

接着就是来处理这个贡献与计算问题了。

我们想要计算的就是,当我们已经知道 一个点 uu,在其他所有树上,比他的深度浅或者同样深度的所有点,记作 VV 集合,贡献为:

vVdep(u)dep(lca(u,v))\sum_{v\in V}\text{dep}(u)-\text{dep}(\text{lca}(u,v))

这个问题,有许多解决方法,不过,我们这里选择使用启发式合并。

启发式合并的关键就是,合并过程复杂度必须要依赖于轻儿子的这个子树的参数(如节点数量,深度等),不能够依赖于遍历重儿子。

不过,这个要求并不难,使用前缀和,搞一搞,就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 计算答案,把轻儿子节点合并进主集合中。
for (auto [dep_son,cnt]:node_dep_cnt_mtx[to]) {
// cnt 是深度为 dep_son,较大的节点的数量(Jerry),get_presum_val 拿到的
// 是所有比 dep_son 小的点的 dep(v)-dep(lca(u,v)) 的这个和
ans+=cnt*get_presum_val(dep_son);
// 深度相同的节点可以反复贡献(可以理解为上面也可以贡献,下面也可以贡献)
ans+=cnt*node_dep_cnt_mtx[u][dep_son]*(dep_son-dep);
// 这个是深度比 dep_son 大的节点的数量
ll num_gt_dep=sum_node-get_presum_num(dep_son);
// 深度比 dep 深度深的节点,也会贡献,因为已经在重儿子中的深度深的节点
// 合并进来的时候还没有这样一个节点,贡献的就是 dep_son-dep(lca)
ans+=num_gt_dep*cnt*(dep_son-dep);
// 这里是顺手进行一个更新
node_dep_cnt_mtx[u][dep_son]+=cnt;
}

注意这个有可能出现重儿子比轻儿子的这个链长短的这个情况(当然可以变为分长儿子/短儿子)。这个时候直接取这个前缀和,因为我们用 map 实现,就会取到 00。这个时候可以用一个匿名 get 函数特判一下这个情况。

这种情况的一个 hack 数据:

1
2
3
4
5
6
1
7 2
3 7
4 6

ans:20

AC代码

AC
https://codeforces.com/contest/2188/submission/361002651

心路历程(WA,TLE,MLE……)

题目大意

给定长度为nn的数组aa。对于整数kk,我们称其为piggy,当且仅当通过执行以下操作任意次数(可能为零),可以将aa以非递减顺序排序:

  • 首先,选择两个索引iijj1i<jn1 \le i < j \le n),使得aiajk|a_i - a_j| \ge k;

  • 然后,交换aia_iaja_j

您需要确定最大的piggy整数kk。如果不存在这样的整数,则输出1-1

思路讲解

不难注意到,我们可以选用最大的数字或者最小的数字去做中转站,

image

乍一看,好像选择最小的数字,还是选择最大的数字,取决于两个数字 totonownow?实际上不是的,我们完全可以换着来,比如说:

image

这样子就实现了 totomnmnnownow 用这个 mxmx,反之亦然,完全可以只根据一个数去选择

okay,那就行了。我们发现,这个 totonownow 一定都是和有序序列中的同位置值不一样的点,因此,我们的答案其实就是:(其中 SS 为所有和有序序列中的同位置值不一样的点的下标集合)

ansminiS(max(mxai,aimn))ans\gets\min_{i\in S}(\max(mx-a_i,a_i-mn))

当然,也可以使用代码中的这个贪心实现。

AC代码

AC
https://codeforces.com/contest/2188/submission/360594620

心路历程(WA,TLE,MLE……)