1. 程式人生 > 其它 >2022春每日一題:Day 33

2022春每日一題:Day 33

題目:[USACO 6.1.3] Cow XOR

沒找到這題具體網址,這個題就是求最大異或區間(總長度儘量小,右端點儘量大)

嗯很顯然一個[l,r]的異或和=s[r]s[l-1],那麼現在有了優秀的n2做法
不難(很難)聯想trie樹,列舉1到n每次把1...i的異或和加入trie樹中,然後跑一遍找最大值(史記上就是trie樹維護這個n^2演算法,降低了複雜度)

程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int N=1e5+5;
using namespace std;
int n,m,tot,ret=-1,lr,rr,a[N],sum;
namespace trietree
{
	struct trie
	{
		int son[2],tag;
	}e[N*22];
	void insert(int x,int id)
	{
		int p=0;
		for(int i=21;i>=0;i--)
		{
			int k=x>>i&1;
			if(!e[p].son[k])
			    e[p].son[k]=++tot;
			p=e[p].son[k];
		}
		e[p].tag=id;
	}
	int query(int x,int &ans)
	{
		int p=0;
		for(int i=21;i>=0;i--)
		{
			int k=x>>i&1;
			if(!e[p].son[k^1])
			    p=e[p].son[k];
			else
			    p=e[p].son[k^1],ans+=1<<i;
		}
		return e[p].tag;
	}
}
using namespace trietree;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		sum^=x;
		insert(sum,i);
		int ans=0;
		int l=query(sum,ans);
		if(ans>ret)
		{
			ret=ans;
			rr=i,lr=l;
		}
	}
	printf("%d %d %d\n",ret,lr+1,rr);
	return 0;
}