HDU - 6955 Xor sum(字典树+贪心)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6955 Xor sum(字典树+贪心)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出一个长度为 n n n 的序列,要求找到一段长度最短的区间,使得异或和大于等于 k k k,如果有多种答案,输出左端点最小的那个

题目分析:倒着维护一下后缀异或和,将后缀异或和插入字典树,然后枚举当前点为左端点,在字典树上贪心即可。设 x x x 为当前后缀值,具体贪心方法如下:

  1. 如果 k k k 的当前位为 0 0 0 ,如果走异或为 1 1 1 这条路的话,答案显然会大于 k k k,所以可以直接用 1 1 1 侧的子树更新答案,同时沿着字典树走异或为 0 0 0 的这条路,因为接下来可能还是会有大于等于 k k k 的情况
  2. 如果 k k k 的当前位为 1 1 1 x x x 只能走异或 1 1 1 这条路,如果不能走直接退出

当走到低时,注意特判一下 x ⊕ k = 0 x \\oplus k=0 xk=0 的情况,在代码中用一行就可以体现

需要注意的是:

  1. 数组大小
  2. 根节点的初始化

代码:

// 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(字典树+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4825 Xor Sum(经典01字典树+贪心)

2021杭州多校6955-xor sum(字典树+异或前缀和)

2021杭州多校6955-xor sum(字典树+异或前缀和)

HDOJ6955Xor sum(异或前缀和,01字典树)

HDU 4825 Xor Sum(01字典树)题解

HDU4825 Xor Sum(贪心+Trie树)