C1. Sheikh (Easy version)
C1. Sheikh (Easy version)
This is the easy version of the problem. The only difference is that in this version $q=1$.
You are given an array of integers $a_1,a_2, \ldots,a_n$.
The cost of a subsegment of the array $[l, r]$, $1 \leq l \leq r \leq n$, is the value $f(l, r) = \operatorname{sum}(l, r) - \operatorname{xor}(l, r)$, where $\operatorname{sum}(l, r) = a_l + a_{l+1} + \ldots + a_r$, and $\operatorname{xor}(l, r) = a_l \oplus a_{l+1} \oplus \ldots \oplus a_r$ ($\oplus$ stands for bitwise XOR).
You will have $q=1$ query. Each query is given by a pair of numbers $L_i$, $R_i$, where $1 \leq L_i \leq R_i \leq n$. You need to find the subsegment $[l,r]$, $L_i \leq l \leq r \leq R_i$, with maximum value $f(l,r)$. If there are several answers, then among them you need to find a subsegment with the minimum length, that is, the minimum value of $r−l+1$.
Input
Each test consists of multiple test cases. The first line contains an integer $t$ $(1 \leq t \leq {10}^{4})$ — the number of test cases. The description of test cases follows.
The first line of each test case contains two integers $n$ and $q$ $(1 \leq n \leq {10}^{5}, q=1)$ — the length of the array and the number of queries.
The second line of each test case contains $n$ integers $a_1,a_2, \ldots,a_n$ $(0 \leq a_i \leq {10}^{9})$ — array elements.
$i$-th of the next $q$ lines of each test case contains two integers $L_i$ and $R_i$ $(1 \leq L_i \leq R_i \leq n)$ — the boundaries in which we need to find the segment.
It is guaranteed that the sum of $n$ over all test cases does not exceed $2 \cdot {10}^{5}$.
It is guaranteed that $L_1=1$ and $R_1=n$.
Output
For each test case print $q$ pairs of numbers $L_i \leq l \leq r \leq R_i$ such that the value $f(l,r)$ is maximum and among such the length $r−l+1$ is minimum. If there are several correct answers, print any of them.
Example
input
6 1 1 0 1 1 2 1 5 10 1 2 3 1 0 2 4 1 3 4 1 0 12 8 3 1 4 5 1 21 32 32 32 10 1 5 7 1 0 1 0 1 0 1 0 1 7
output
1 1 1 1 1 1 2 3 2 3 2 4
Note
In the first test case, $f(1,1)=0−0=0$.
In the second test case, $f(1,1)=5−5=0$, $f(2,2)=10−10=0$. Note that $f(1, 2) = (10 + 5) - (10 \oplus 5) = 0$, but we need to find a subsegment with the minimum length among the maximum values of $f(l,r)$. So, only segments $[1,1]$ and $[2,2]$ are the correct answers.
In the fourth test case, $f(2, 3) = (12 + 8) - (12 \oplus 8) = 16$.
There are two correct answers in the fifth test case, since $f(2,3)=f(3,4)$ and their lengths are equal.
解题思路
当$l$固定后,$f(l,r)$是一个随着$r$增加的递增函数,即$f(l, r) \leq f(l, r + 1)$。当加入一个新的元素$x$,此时$\operatorname{sum}$增加了$x$,而$\operatorname{xor}$的增量不会超过$x$。要知道$\operatorname{xor}$本质是不进位加法,因此$a \oplus x \leq a + x$。所以假设$f(l, r) = s - sx$,那么$f(l, r + 1) = (s + x) - (sx \oplus x) \geq (s + x) - (sx + x) = s - sx$,因此$f(l, r + 1) - f(l, r) \geq (s - sx) - (s - sx) = 0$,即当$l$固定后,$f(l,r)$是一个递增函数。如果没想到这一步的话那这道题就做不出来了。
因此,我们知道当$l$固定后,最大值就是$f(l, n)$,又因为我们要使得区间长度尽可能小,且$f(l,r)$是一个递增函数,因此我们可以二分出值为$f(l, n)$最靠左的一个右端点。
因此做法就是枚举左端点$l$,对于固定的左端点二分出最靠左且值为$f(l, n)$的右端点。
AC代码如下,时间复杂度为$O(n \log{n})$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 LL s[N], sx[N]; 9 10 void solve() { 11 int n, m; 12 scanf("%d %d", &n, &m); 13 for (int i = 1; i <= n; i++) { 14 int x; 15 scanf("%d", &x); 16 s[i] = s[i - 1] + x; // 预处理前缀和 17 sx[i] = sx[i - 1] ^ x; // 预处理前缀异或和 18 } 19 20 while (m--) { 21 int x, y; 22 scanf("%d %d", &x, &y); 23 LL maxv = -1, a, b; // maxv是最大f值,a、b是答案的左右端点 24 for (int i = x; i <= y; i++) { // 枚举左端点i 25 int l = i, r = y; // 在区间[i, y]中找到最靠左的右端点r,使得f(i,r) = f(i,y) 26 LL t = s[y] - s[i - 1] - (sx[y] ^ sx[i - 1]); // f(i,y) 27 while (l < r) { // 二分右端点 28 int mid = l + r >> 1; 29 if (s[mid] - s[i - 1] - (sx[mid] ^ sx[i - 1]) >= t) r = mid; 30 else l = mid + 1; 31 } 32 if (t > maxv) { 33 maxv = s[l] - s[i - 1] - (sx[l] ^ sx[i - 1]); 34 a = i, b = l; 35 } 36 else if (t == maxv && b - a > l - i) { 37 a = i, b = l; 38 } 39 } 40 printf("%d %d\n", a, b); 41 } 42 } 43 44 int main() { 45 int t; 46 scanf("%d", &t); 47 while (t--) { 48 solve(); 49 } 50 51 return 0; 52 }
参考资料
Codeforces Round #830 (Div. 2) Editorial:https://codeforces.com/blog/entry/108327
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16835098.html