【每日一题】 奶牛异或题解(01Trie)
奶牛异或
https://ac.nowcoder.com/acm/problem/22998
Description
农民约翰在喂奶牛的时候被另一个问题卡住了。他的所有N(1 <= N <= 100,000)个奶牛在他面前排成一行(按序号1..N的顺序),按照它们的社会等级排序。奶牛#1有最高的社会等级,奶牛#N最低。每个奶牛同时被指定了一个不唯一的附加值,这个数在 的范围内。
帮助农民约翰找出应该从哪一头奶牛开始喂,使得从这头奶牛开始的一个连续的子序列上,奶牛的附加值的异或最大。
如果有多个这样的子序列,选择结尾的奶牛社会等级最高的。如果还不唯一,选择最短的。
Solution
还是01Trie的经典题目,取一个区间的异或值
令前缀异或和
显然有
于是我们把问题转化为在前缀异或和里找两个数字,使得他们异或最大即可。
注意res初始值要赋值为负数!!!我在这里wa了好几次0.0
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int a[N];
int trie[N * 50][2];
map<int, int> mp;
int tot;
void add(int x, int i) {
int rt = 0;
for(int i = 30; i >= 0; i--) {
int cur = ((x >> i) & 1);
if(!trie[rt][cur]) trie[rt][cur] = ++tot;
rt = trie[rt][cur];
}
mp[rt] = i;
}
pair<int, int> query(int x) {
int ans(0), rt(0);
int pos(0);
for(int i = 30; i >= 0; i--) {
int cur = ((x >> i) & 1);
if(trie[rt][cur ^ 1]) {
ans |= (1LL << i);
rt = trie[rt][cur ^ 1];
} else {
rt = trie[rt][cur];
}
}
pos = mp[rt];
return make_pair(ans, pos);
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n; cin >> n;
int res(-1);
for(int i = 1; i <= n; i++) {
cin >> a[i];
a[i] ^= a[i - 1];
}
int pos = -1, l, r;
add(0, 0);
for(int i = 1; i <= n; i++) {
auto ans = query(a[i]);
if(res < ans.first) {
res = ans.first;
r = i;
l = ans.second;
}
add(a[i], i);
}
cout << res << ' ' << l + 1 << ' ' << r << '\n';
return 0;
} Kurisu与牛客的每日一题 文章被收录于专栏
每日一题
联想公司福利 1477人发布