D - Xor Sum 2
题意:
找出所有满足
Al+Al+1+...+Ar=Al xor Al+1 xor ... xor Ar
A
l
+
A
l
+
1
+
.
.
.
+
A
r
=
A
l
x
o
r
A
l
+
1
x
o
r
.
.
.
x
o
r
A
r
的区间
[l,r]
[
l
,
r
]
的个数。
思路:
根据异或的性质,我们知道一个区间
[l,r]
[
l
,
r
]
所有元素同一个位的1的数量不超过一个就可以了,因为超过一个的话加法会进位,就不满足条件了。直接尺取,时间
O(n)
O
(
n
)
。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 3e5 + 10;
using namespace std;
ll arr[maxn];
int main() {
ios::sync_with_stdio(0);
ll sum = 0, xr = 0, ans = 0, j = 1;
int n; cin >> n;
for(int i = 1; i <= n; i++) {
cin >> arr[i];
while(sum + arr[i] != (xr ^ arr[i])) {
sum -= arr[j]; xr ^= arr[j];
ans += i - j; j++;
}
sum += arr[i]; xr ^= arr[i];
}
while(j <= n) { ans += n + 1 - j; j++; }
cout << ans << endl;
return 0;
}
E - Range Minimum Queries
题意:
一个数列,每次选择长度为
k
k
的区间,删掉其中最小值,可以删至少次,使删除的数中最大值 - 最小值最小,输出最小值。
思路:
可以暴力枚举最小值
x
x
,小于最小值的数就相当于在所有数串成链表后那些位置断开了,次每次找最小的未被删除的
⩾ x
⩾
x
的最小的
y
y
,看它所在的那块剩余链的位置是否大于,大于的话则可以删除。最后取所有答案的最小值即可。时间
O(n2)
O
(
n
2
)
。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 2e3 + 10;
const int INF = 2e9 + 10;
using namespace std;
typedef pair<int, int> pa;
pa res[maxn];
int n, m, T, kase = 1;
int a[maxn], b[maxn];
int pre[maxn], size[maxn];
void build(int x) {
int tot = 0;
memset(size, 0, sizeof size);
for(int i = 1; i <= n; i++) {
if(a[i] < x) {
while(i <= n && a[i] < x) i++;
i--; tot++; continue;
}
pre[i] = tot; size[tot]++;
}
}
int solve(int x, int q) {
int t = 0, flag = 0;
for(int i = 0; i < n; i++) {
if(res[i].first < x) continue;
int id = res[i].second, p = pre[id];
if(size[p] < m) continue;
if(res[i].first == x) flag = 1;
size[p]--; q--;
if(!q) { t = res[i].first - x; break; }
}
if(!flag || q) return INF;
return t;
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m >> T;
for(int i = 1; i <= n; i++) {
cin >> a[i];
b[i - 1] = a[i];
res[i - 1] = pa(a[i], i);
}
sort(b, b + n);
sort(res, res + n);
int cnt = unique(b, b + n) - b;
int ans = INF;
for(int i = 0; i < cnt; i++) {
int x = b[i];
build(x); ans = min(ans, solve(x, T));
}
cout << ans << endl;
return 0;
}