题解/算法 {AtCoder355/E - Guess the Sum}

题解/算法 {AtCoder355/E - Guess the Sum}

@LINK: https://atcoder.jp/contests/abc355/tasks/abc355_e;

首先 读懂题 并且把他简化 非常重要, 因为题目中涉及了l,r, I, J 看着就很复杂, 明明是查询query(l,r)区间 但是 你还要把他转换成I,J来输出, 因此 你要看到query(l,r)的本质是什么: l=(1<<I)*J, r=l+(1<<I)-1这说明: r-l+1的长度 是1<<I 也就是说 查询的区间长度为1<<I二次幂, 其次还有一个条件 即l % len == 0l是区间长度的倍数; 简而简之, 查询的区间长度是二次幂 左端点是区间长度的倍数;
因此, 对于整个数组的范围[0, R] (R==(1<<N)-1):
+(查询区间长度为1): 把[0,R][0]开始 划分为若干个长度为1的子区间 即[0-0] [1-1] [2-2] [3-3] ...;
+(查询区间长度为2): 把[0,R][0]开始 划分为若干个长度为2的子区间 即[0-1] [2-3] [4-5] [6-7] ...;
+(查询区间长度为4): 把[0,R][0]开始 划分为若干个长度为4的子区间 即[0-3] [4-7] ...;
+(查询区间长度为8): 把[0,R][0]开始 划分为若干个长度为8的子区间 即[0-7] [8-15] ...;

+(查询区间长度为1<<N): 则只有[0, R];
. 其实你仔细观察下 这些可以查询的区间, 就是 区间[0,R]所对应的线段树区间 (区间长度为1的这些区间 就对应线段树的叶子节点); (不过这个题的正解 虽然与线段树无关…);

注意, 题目要求的是 最小查询次数;

错误做法: 将[L,R]拆分成若干个子区间, 他们之和 就是答案;
. . 错误, 因为题目要求最小查询次数, 比如[0,1,2,...,7,...] 比如L=1,R=7 按照你的贪心 答案是[1,2] + [3,3] + [4-7] 而正解是 [0,7] - [0,0];

也就是 会涉及到区间相减的情况, 比如答案区间[L,R] 他对应若干个区间[li, ri], 我们要将每个区间 添加一个符号+1 / -1, 使得这些区间之和 是等于[L,R]的(换句话说[L,R]里每个元素出现1次 而<L || >R的元素 都出现0次), 这就是新的问题模型, 可是要怎么做呢?
#错误#: 容易想到前缀和 因为他可以处理区间相减, 但是 前缀和只能求[l,r] = [0,r] - [0,l-1], 而这个问题 [l,r]的答案 是会涉及到>r的区间的 (比如L=0, R=6] 答案是[0-7] - [7,7]), 换句话说 这个题目 是由后效性的 而前缀和是无后效性的 即在[i]处 只有<i是正确的;

重新回到正确思路来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值