微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对二进制字符串进行范围查询?

如何解决对二进制字符串进行范围查询?

二进制十进制

我们得到了一个长度为n 二进制字符串 S,其中每个字符为'1'或'0'

我们被要求对字符串执行几个查询

在每个查询中,我们都得到整数 L R 。 并且我们必须以十进制表示形式来告诉子字符串 S [l..r] 的值。

示例测试用例:

Input:

1011 (string S)
5    (number of queries)
1 1  (l,r)
2 2
1 2
2 4
1 4

Output:
1      (1 * 2^0 == 1)
0
2
3      (0 * 2^2 + 1 * 2^1 + 1 * 2^0)
11     (1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 11)

约束

1 < N < 10^5
1 < Q < 10^5

由于数量可能非常大,我们需要以模数 10 ^ 9 + 7进行打印。

方法

因此,基本上,我们需要将二进制表示形式的子字符串S [l..r]转换为十进制。

预先计算对所有 i:[0,n-1] S [i ... n-1] 的结果 阵列B 中的“ strong”。 因此,现在 B [i] 代表子字符串 S [i..n-1] 的十进制数字表示。

vector<int> pow(1e5,1);
for(int i = 1; i < 1e5; i++) {
    pow[i] = (pow[i - 1] * 2) % mod;
}

string s;
getline(cin,s);
vector<int> B(n,0);
int prev = 0;
for(int i = 0; i < n; i++) {
    B[(n - 1) - i] = (prev + (s[(n - 1) - i] == '1' ? pow[i] : 0)) % mod;
    prev = B[(n - 1) - i];
}

while(q--) {
    int l,r;
    cin >> l >> r;
    cout << ((B[l] - (r + 1 < n ? B[r + 1] : 0) + mod) % mod) / pow[n - (r + 1)]<< "\n";
}

return 0;

通过上述方法,仅通过了示例测试用例,其他所有情况都给出了错误答案(WA)

我什至尝试使用段树解决此问题,但这也不起作用。

解决此问题的正确方法是什么?

解决方法

V[k]定义为S的第k位数字。

然后是子字符串S[l..r] = (V[l] - V[r+1]) / 2^(n - r - 1)的值。 (类似的事情,我可能会犯一个错误。请举一些小例子。)

现在,关于10^9 + 7的有用事实是它是素数。 (前10个数字为质数。)这意味着除以2等于乘以2^(10^9 + 5)。您可以通过重复平方求出该常数。使用重复平方可以非常有效地将常数提高到高倍。

以此,您可以为V创建一个查找表,然后及时O(log(n))进行查询。

,

这似乎与常规求和范围查询相同,除了(1)我们需要存储部分和mod 10 ^ 9 + 7,(2)在检索期间,我们需要“移位”全部和的相关部分用右边部分的长度求和。在这种情况下,要“移动”将意味着乘以2 ^(length_of_suffix)mod 10 ^ 9 +7。当然,将段mod 10 ^ 9 + 7相加。

但是btilly的answer似乎要简单得多:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。