Round #6 C.Alice, Bob and Chocolate

本文解析了Codeforces上一道关于两人同时吃巧克力棒的问题。通过计算巧克力棒总长度的一半,利用二分查找确定每人能吃到的巧克力数量,并特别处理了双方同时看到最后一根巧克力棒的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:Codeforces Round #6 Div.2

题目大意:Alice和Bob吃巧克力棒,给出一堆巧克力棒,长度不一,吃巧克力棒的速度是相同且均匀的。Alice从左边的巧克力棒开始吃,Bob同时从右边吃。如果两人同时看到最后一根巧克力棒,Bob会让给Alice吃。吃完为止。输出两人吃的巧克力棒个数。

思路:既然速度是均匀的,那么可以根据巧克力棒长度之和的一半key来判定两人吃的个数。保存巧克力棒的前缀和,在前缀和当中找到这个key,如果找不到,就找到它的邻居。关键就在于“争议”巧克力棒的判定。(当两人同时看到最后一根巧克力棒……)

我们可以找到小于或等于key的前缀和,作为Alice的总量(肯定属于Alice),然后中间留下一根棒,后面的和最为Bob的总量,单独处理中间这根争议棒。

当时做不对这道题……因为——1.二分姿势不标准 2.判定写不对(对前缀和的理解)。

使用二分的时候,如果对边界不会判定,可以使用一个ret来“记路”。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int sum[100010];

int main() {
	int n, a, key;
	scanf("%d", &n);
	sum[0] = 0;
	for(int i = 1; i <= n; i++) {
		scanf("%d", &a);
		sum[i] = sum[i-1] + a;
	}
	key = sum[n] / 2;
	int l = 1, r = n, ans = 0;
	while(l != r) {
		int m = (l+r) >> 1;
		if(sum[m] <= key) {
			ans = m;
			l = m + 1;
		}//明显sum[ans]是不大于key的
		else
			r = m;
	}//用ans来“记路”
	if(sum[ans] <= sum[n] - sum[ans+1])
		ans++;//对争议棒进行判定,相等或者Alice的少,这根就要给Alice
	printf("%d %d\n", ans, n - ans);
	return 0;
}


<think>我们有一个MySQL的CASE表达式,需要转换为OpenGauss兼容的语法。原语句如下:CASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})ELSECONCAT(&#39;-&#39;,ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit}))ENDAS"value"在OpenGauss中,我们需要注意以下几点:1.OpenGauss支持标准的CASE表达式,所以基本结构可以保持不变。2.在MySQL中,CONCAT函数可以连接多个字符串,而OpenGauss同样支持CONCAT函数,但需要注意的是,如果连接的对象不是字符串类型,可能需要转换。不过,这里我们连接的是一个字符串&#39;-&#39;和一个数值,在MySQL中数值会自动转换为字符串,但在OpenGauss中,我们最好显式地将数值转换为字符串以避免潜在问题。3.另外,OpenGauss中字符串连接也可以使用`||`操作符,这可能是更常见的做法。4.在OpenGauss中,ROUND函数的使用与MySQL相同,都是两个参数:第一个是数值,第二个是保留的小数位数。因此,我们可以将上述语句改写为:-保持CASE结构不变。-在ELSE部分,我们可以使用`||`操作符来连接字符串,并将ROUND的结果转换为字符串。但是,注意ROUND返回的是数值,我们可以使用`CAST`或者`::text`将其转换为字符串。改写后的语句如下:```sqlCASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textELSE&#39;-&#39;||ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textENDAS"value"```但是,这里有一个问题:THEN子句返回的是数值,而ELSE子句返回的是字符串。这样会导致整个CASE表达式的结果类型不一致。在MySQL中,可能会隐式转换,但为了在OpenGauss中确保类型一致,我们可以统一返回字符串。因此,我们可以将THEN子句也转换为字符串,这样整个CASE表达式都返回字符串。修改如下:```sqlCASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textELSE&#39;-&#39;||ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textENDAS"value"```或者,我们也可以使用CAST函数:```sqlCASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENCAST(ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})ASVARCHAR)ELSE&#39;-&#39;||CAST(ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})ASVARCHAR)ENDAS"value"```另外,我们注意到在MySQL原语句中,当值为0时,返回的是0(数值),而其他情况返回的是带负号的字符串。在OpenGauss中,我们统一返回字符串,这样应用层处理起来可能更一致。另外,我们还可以简化:由于在THEN和ELSE中都要计算相同的ROUND表达式,我们可以考虑使用一个公共子表达式来避免重复计算。但是,在SQL中,我们可以使用子查询或者WITH子句,但在这种表达式内部,我们可以将计算的结果赋给一个变量(在存储过程中)?不过,在这个单表达式情况下,我们无法避免重复计算。但我们可以将整个计算提取到外层,不过这样可能会改变查询结构。如果不想改变结构,我们可以保持重复计算,因为这里的计算并不复杂。但是,如果考虑到性能,我们可以将其改写为子查询,但原问题只是要求改写表达式,所以我们先保持结构不变。另外,在OpenGauss中,我们也可以使用`to_char`函数来格式化数值,但这里的需求是:当值为0时显示0(不带负号),否则显示负号加绝对值(但注意:原表达式在ELSE中直接添加了负号,这意味着原表达式在MySQL中可能是用于显示一个负数,但实际上,原表达式在条件判断中判断的是四舍五入后的值是否为0,而不是判断正负。所以这里需要注意:原表达式并不是根据正负来添加负号,而是根据是否为0来决定是否添加负号?这看起来有些奇怪。让我们重新审视原表达式:-条件:当四舍五入后的值等于0时,返回0(数值),否则返回一个字符串,该字符串是四舍五入后的值前面加一个负号。这逻辑似乎不对,因为如果值大于0,也会被加上负号?这显然不是我们想要的。所以,我怀疑原MySQL语句的意图可能是:当值小于0时,显示负号,而当值为0时显示0?但这里条件判断的是整个表达式是否为0,而不管正负。实际上,原逻辑是:如果四舍五入后的值等于0,则显示0(没有负号),否则,显示一个带负号的值。但这样,即使是正数,只要不等于0,也会被显示为负数?这显然不合理。因此,我怀疑这个表达式可能有逻辑错误。但根据用户提供的表达式,我们只负责语法转换,不改变逻辑。所以,我们按照原逻辑进行转换,但请注意,这个逻辑可能不是用户想要的(因为正数也会被加上负号)。不过,用户要求的是语法转换,所以我们先按原逻辑转换。总结:转换后的OpenGauss语法为:```sqlCASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textELSE&#39;-&#39;||ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})::textENDAS"value"```或者使用CAST:```sqlCASEWHENROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})=0THENCAST(ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})ASVARCHAR)ELSE&#39;-&#39;||CAST(ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit})ASVARCHAR)ENDAS"value"```注意:这里的`${item.analysisBelongColumn}`和`#{item.unitValue}`、`#{item.decimalDigit}`是占位符,在OpenGauss中同样适用,只要这些占位符在应用程序中被正确替换。另外,在OpenGauss中,我们也可以使用`to_char`函数来控制数值格式,但这里我们只需要简单的转换,所以使用`::text`或`CAST`即可。最后,我们输出转换后的SQL语句。</think>要将 MySQL 中的 `CASE` 表达式转换为 OpenGauss 兼容语法,需要注意以下关键点: ### 转换后的 OpenGauss 语法 ```sql CASE WHEN ROUND(COALESCE(${item.analysisBelongColumn}, 0) / #{item.unitValue}, #{item.decimalDigit}) = 0 THEN TO_CHAR(ROUND(COALESCE(${item.analysisBelongColumn}, 0) / #{item.unitValue}, #{item.decimalDigit), &#39;FM9999999990.9999&#39;) ELSE &#39;-&#39; || TO_CHAR(ROUND(COALESCE(${item.analysisBelongColumn}, 0) / #{item.unitValue}, #{item.decimalDigit), &#39;FM9999999990.9999&#39;) END AS "value" ``` ### 修改说明: 1. **字符串连接操作符** MySQL 的 `CONCAT()` 函数需替换为 OpenGauss 的字符串连接符 `||` 2. **数值转字符串处理** OpenGauss 需要显式将数值转换为字符串: - 使用 `TO_CHAR()` 函数替代隐式转换 - 格式模式 `&#39;FM9999999990.9999&#39;` 的作用: - `FM`:删除前导空格 - `9999999990`:整数部分格式化(9 表示可选数字,0 表示强制显示) - `.9999`:小数部分占位符,位数应与 `#{item.decimalDigit}` 匹配 3. **类型一致性** 确保 THEN 和 ELSE 分支返回相同数据类型(均为字符串) 4. **小数位控制** `ROUND()` 函数在 OpenGauss 中行为与 MySQL 一致,保留原始参数即可 ### 关键差异总结: | 特性 | MySQL | OpenGauss | |--------------|---------------------|---------------------| | 字符串连接 | `CONCAT()` | `||` 操作符 | | 数值转字符串 | 隐式转换 | 显式 `TO_CHAR()` | | 格式化控制 | 无特别处理 | 需格式模式参数 | ### 优化建议: 1. **动态小数位处理** 若 `#{item.decimalDigit}` 可变,可动态生成格式模式: ```sql &#39;FM9999999990.&#39; || LPAD(&#39;&#39;, #{item.decimalDigit}, &#39;9&#39;) ``` 2. **空值处理增强** `COALESCE(..., 0)` 已覆盖空值情况,符合 OpenGauss 的空值处理逻辑 3. **性能考虑** 重复计算 `ROUND(...)` 可提取为公共表达式: ```sql WITH calc AS ( SELECT ROUND(COALESCE(${item.analysisBelongColumn},0)/#{item.unitValue},#{item.decimalDigit}) AS val ) SELECT CASE WHEN val = 0 THEN TO_CHAR(val, &#39;FM9999999990.9999&#39;) ELSE &#39;-&#39; || TO_CHAR(val, &#39;FM9999999990.9999&#39;) END AS "value" FROM calc ``` > 此转换保持了原始逻辑:当四舍五入值为 0 时直接显示,否则添加负号前缀。实际业务中请验证负号生成逻辑是否符合需求[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值