HDU - 6955 Xor sum(字典树+贪心)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6955 Xor sum(字典树+贪心)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出一个长度为 n n n 的序列,要求找到一段长度最短的区间,使得异或和大于等于 k k k,如果有多种答案,输出左端点最小的那个
题目分析:倒着维护一下后缀异或和,将后缀异或和插入字典树,然后枚举当前点为左端点,在字典树上贪心即可。设 x x x 为当前后缀值,具体贪心方法如下:
- 如果 k k k 的当前位为 0 0 0 ,如果走异或为 1 1 1 这条路的话,答案显然会大于 k k k,所以可以直接用 1 1 1 侧的子树更新答案,同时沿着字典树走异或为 0 0 0 的这条路,因为接下来可能还是会有大于等于 k k k 的情况
- 如果 k k k 的当前位为 1 1 1, x x x 只能走异或 1 1 1 这条路,如果不能走直接退出
当走到低时,注意特判一下 x ⊕ k = 0 x \\oplus k=0 x⊕k=0 的情况,在代码中用一行就可以体现
需要注意的是:
- 数组大小
- 根节点的初始化
代码:
// Problem: Xor sum
// Contest: Virtual Judge - HDU
// URL: https://vjudge.net/problem/HDU-6955
// Memory Limit: 524 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
int a[N],trie[N*30][2],mmin[N*30],tot,ans;
int newnode() {
tot++;
trie[tot][0]=trie[tot][1]=0;
mmin[tot]=inf;
return tot;
}
void insert(int num,int id) {
int pos=0;
for(int i=29;i>=0;i--) {
int to=(num>>i)&1;
if(!trie[pos][to]) {
trie[pos][to]=newnode();
}
pos=trie[pos][to];
mmin[pos]=min(mmin[pos],id);
}
}
void search(int num,int k) {
int pos=0;
for(int i=29;i>=0;i--) {
int to=(num>>i)&1;
if(((k>>i)&1)==0) {
ans=min(ans,mmin[trie[pos][!to]]);
pos=trie[pos][to];
} else {
pos=trie[pos][!to];
}
if(!pos) {
return;
}
}
ans=min(ans,mmin[pos]);//特判num==k的情况
}
void init() {
tot=-1;
newnode();
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--) {
init();
int n,k;
read(n),read(k);
for(int i=1;i<=n;i++) {
read(a[i]);
}
int l=-1,r=-1,sum=0;
insert(0,n+1);
for(int i=n;i>=1;i--) {
sum^=a[i];
ans=inf;
search(sum,k);
if(ans!=inf) {
if(l==-1||ans-i<=r-l) {
l=i,r=ans;
}
}
insert(sum,i);
}
if(l==-1) {
cout<<-1<<endl;
} else {
cout<<l<<' '<<r-1<<endl;
}
}
return 0;
}
以上是关于HDU - 6955 Xor sum(字典树+贪心)的主要内容,如果未能解决你的问题,请参考以下文章
2021杭州多校6955-xor sum(字典树+异或前缀和)