Codeforces Round #717 (Div. 2) A—C 反思总结

比赛链接:https://codeforces.com/contest/1516

A

题目大意

n个元素,最多k次操作,每次操作选择两个元素,其中一个++另一个–,不能出现负数。输出最多k次操作后,字典序最小的元素序列。

解题情况

一共 wa 了两发。

wa了第一发的时候没有检查语法错误。
而是直接找逻辑错误,结果改了跟没改一样wa了第二发。

wa了第二发的时候才认真找错误:
发现错误有两点:

  1. 定义加了 long long 但输入的时候用的是%d 而不是%lld
  2. 题目说的是字典序最大,并且没上限,那只需要每次选择最前面的首非0项,和最后一位就可以。 而我的做法是把最前面那项减到0后,l++,r–。不能r–。

B

题目大意

n个元素,可进行任意次操作,把两个相邻元素的合并成他们的异或和。

思路

最开始以为跟区间dp有关,但n是2000级别,区间dp是O( n 3 n ^{3} n3).
后面一想,反正是相邻的,把它分成两个区间,然后每个区间都异或和,枚举 k (两个区间的边界)。异或和 就用 一个前缀异或和、一个后缀。
因为异或具有交换律,结合律。

结果wa了一发,被3 3 3.这个数据hack了。
因为还有分成3段的情况。
于是在判断完两个区间后,如果还是NO就判断三个区间的情况。
枚举中间区间的长度,利用前缀异或和的性质:
像前缀和一样,sum[l,r] = sum[r] - sum[l], 换成sum[l,r] = sum[r] ^ sum[l]. 来处理O(1)处理中间区间,这样复杂度是O( n 2 n^{2} n2).

解题情况

也wa了两发,
第一发 把后缀和写错了,把ed[i] = ed[i+1] ^ a[i],写成了ed[i] = ed[i-1] ^ a[i]。
第二发 就是只考虑了两个区间。

需要注意的点

队友被hack了,是因为异或和优先级小于 ==。要写成这样 if ( (sum[i]^sum[j])==sum[i] )

C

题目大意

n个元素,求删去最少的元素,使得 它不能分成两个 总和相等的集合。

思路

两个集合相等,自然而然想到了天平问题
看一下n=100,a < 2000,没错可以用01背包来判断,当前集合是否存在 可以分成两个总和相等集合的情况。
但后面一想,如果每次删除都判断,时间肯定会炸,而且也不知道要删多少次。

于是后面在01背包的dp中,记录非0的 放入物品最多的情况。但最后也没调出来。

看别人代码发现思路很简单,先01背包判断。
如果能分,就删除一个奇数。
如果没有奇数,就把所有的数都除2,直到有一个奇数。
也就是说,最多只删除一个元素就可以。
为什么可以除2能,因为所有元素都是偶数的情况下,全部都除2不影响它们之间的相对倍数关系,也就是说,原来能凑成的,之后也能凑成。

解题情况

赛时没写出来。

总结

  1. 交之前注意基本语法问题(%lld)
  2. 位运算的优先级 小于 等号,使用位运算就要用括号!!
  3. 先思考再码代码,三题都是题目还没思考情况,自己的算法没有进行合理性验证就上手,导致思路固定,后面很难改思路。
  4. 赛时的思维能力还需要提高,但比以前其实提高了不少,起码每题一看就能想到正确的解法(B题立马前后缀处理,C题很快就意识到是01背包),只是算法的细节没有考虑清楚。
  5. 继续冲!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值