项链 题解
项链 题解
出题人是小丑,写了一个很难的写法,而且给这个题目评了很难的难度,结果被方大佬瞬间秒了,提出了极其简单的方法。
出题人的垃圾解法
运用莫队+二分,莫队是离线做法,但是可以快速解决一大批次的问题,二分虽然需要在线做,但是这个题目破环成链后,实际上是对于每个左端点,求出最靠左的右端点,所以可以一次将所有的二分信息存下来,用莫队一次处理,最多会二分 \(logn\) 次,每次二分算 \(check\) 函数的复杂度是 \(n根n\),总复杂度是 \(O(nlogn根n)\)。
Show Code
#include
#define int long long
using namespace std;
auto mread = [](){
int x;
scanf("%lld", &x);
return x;
};
const int N = 2e5 + 5;
int n, m, k, a[N], s[N], sum[N], res[N], l[N], r[N], n2, n3;
struct Node{
int l, r, id;
}p[N];
void solve(){
int qn = sqrt(n);
sort(p + 1, p + 1 + n2, [&](Node a, Node b){
if(a.l / qn == b.l / qn)
return a.r < b.r;
return a.l < b.l;
});
int l = 1, r = 0, ans = 0;
memset(sum, 0, sizeof(sum));
sum[0] = 1;
for(int i = 1; i <= n2; i ++){
while(l > p[i].l){
l --;
int t = s[l - 1] ^ k;
ans += sum[t];
sum[s[l - 1]] ++;
}
while(r < p[i].r){
r ++;
int t = s[r] ^ k;
ans += sum[t];
sum[s[r]] ++;
}
while(l < p[i].l){
int t = s[l - 1] ^ k;
sum[s[l - 1]] --;
ans -= sum[t];
l ++;
}
while(r > p[i].r){
int t = s[r] ^ k;
sum[s[r]] --;
ans -= sum[t];
r --;
}
res[p[i].id] = ans;
}
}
bool makeBool(){
for(int i = 1; i <= n3; i ++){
n2 ++;
p[n2].l = i, p[n2].r = i + n3 - 1;
p[n2].id = i;
}
solve();
for(int i = 1; i <= n3; i ++){
if(res[i] >= m)
return 1;
}
return 0;
}
signed main(){
n = mread(), m = mread(), k = mread();
n3 = n;
for(int i = 1; i <= n; i ++)
a[i] = mread();
for(int i = n + 1; i <= n + n - 1; i ++)
a[i] = a[i - n];
n = n + n - 1;
for(int i = 1; i <= n; i ++)
s[i] = s[i - 1] ^ a[i];
if(makeBool() == 0){
printf("-1");
return 0;
}
for(int i = 1; i <= n3; i ++)
l[i] = 1, r[i] = n3;
while(1){
n2 = 0;
for(int i = 1; i <= n3; i ++){
if(l[i] < r[i]){
n2 ++;
int mid = (l[i] + r[i]) >> 1;
p[n2].l = i, p[n2].r = i + mid - 1;
p[n2].id = i;
}
}
if(n2 == 0)
break;
solve();
for(int i = 1; i <= n3; i ++){
if(l[i] < r[i]){
int mid = (l[i] + r[i]) >> 1;
if(res[i] >= m)
r[i] = mid;
else
l[i] = mid + 1;
}
}
}
int ans = LONG_LONG_MAX;
for(int i = 1; i <= n3; i ++)
ans = min(ans, l[i]);
printf("%lld", ans);
return 0;
}
方大佬的牛牛解法
简单双指针,基本上就是双指针板子题,很简单。出题人被他的垃圾解法迷昏了眼,照着解法出题,结果忽视了这个极其简单的解法。
后事
-
出题人试图找到只能用他的垃圾解法解的题目,结果方大佬证明出来不可能。
-
出题人试图研究三分+莫队,但是方大佬用一个较为复杂的双指针解决了。
-
出题人将会继续探寻 在线算法+离线算法 的巧妙结合和超凡效果。

浙公网安备 33010602011771号