CF282 E Sausage Maximization[trie树]

给n个数

求异或前缀(从前连续取一些数全作异或)和异或后缀(从后连续取一些数全作异或)异或的最大值

好坑啊,指针好坑啊

第一道trie树

简单说下解法(其实壳还是不深):

先异或所有数作为初始后缀

然后从前往后的数逐个从后缀出来,进入前缀,

在这个过程中,都把当前前缀变成二进制压入trie,然后当前后缀变成二进制从高位到低位尽量取和它数位不同的值,沿着trie往下走,得到一个最好的数,然后和后缀异或,维护最大值

简直了,指针就是坑

其实还是自己有点坑

说下遇到的坑吧

一开始没有全存64位数(导致可能一个长为30的后缀匹配出来的”最优“前缀长度为6什么的)

然后,我判断每个数位的时候是这样的    num&(1<<i),,,显然错了,应该是(num>>i)&1

还有,应该是把prefix压入trie,我却把number[i]压入trie

还有就是。。。1<<55是错的,应该是1LL<<55

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAX 5
typedef struct Trie   {
	Trie *next[MAX];
	long long v;   //根据需要变化
};
Trie root;
void createTrie(char *str) {
	long long len = strlen(str);
	Trie *p = &root, *q;
	for(long long i=0; i<len; ++i) {
		long long id = str[i]-'0';//这里按需求改
		if(p->next[id] == NULL) {
			q = (Trie *)malloc(sizeof(Trie));
			q->v = 1;    //初始v==1
			for(long long j=0; j<MAX; ++j)
				q->next[j] = NULL;
			p->next[id] = q;
			p = p->next[id];
		} else {
			p->next[id]->v++;
			p = p->next[id];
		}
	}
	p->v = -1;   //若为结尾,则将v改成-1表示
}
long long findTrie(char *str) {
	long long len = strlen(str);
	Trie *p = &root;
	for(long long i=0; i<len; ++i) {
		long long id = str[i]-'0';//这里按需求改
		p = p->next[id];
		if(p == NULL)   //若为空集,表示不存以此为前缀的串
			return 0;
		if(p->v == -1)   //字符集中已有串是此串的前缀
			return -1;
	}
	return -1;   //此串是字符集中某串的前缀
}
long long dealTrie(Trie* T,bool isroot) {
	long long i;
	if(T==NULL)
		return 0;
	for(i=0;i<MAX;i++) {
		if(T->next[i]!=NULL)
			dealTrie(T->next[i],false);
	}
	if(!isroot) free(T);
	return 0;
}
const long long NN=111111;
long long f[NN];
#define SAVE 62
void get_bina(long long s,char* to){
	long long que=0;
	for(long long i=SAVE;i>=0;i--){
		to[que++]=((s>>i)&1)+'0';//应该是 (s>>i)&1
	}
	to[que]='\0';
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("/home/rainto96/in.txt","r",stdin);
#endif
	long long n;cin>>n;
	for(long long i=1;i<=n;i++){
		cin>>f[i];
	}
	long long prefix=0,postfix=0,ans=0;
	for(long long i=1;i<=n;i++) postfix^=f[i];//初始后缀
	ans=postfix;//ans初始就是取所有后缀
	for(long long i=1;i<=n;i++){
		postfix^=f[i];
		prefix^=f[i];
		char tmp[99];
		get_bina(prefix,tmp);//把当前前缀变成二进制
		createTrie(tmp);//把当前前缀压入trie
		get_bina(postfix,tmp);//把当前后缀编程二进制

		Trie* p =&root;
		long long len=strlen(tmp);
		long long get_num=0;
		ans=max(ans,postfix);//不取前缀
		for(long long i=0;i<=SAVE;i++){//逐个取
			long long want = 1 - (tmp[i]-'0');//最优匹配
			if(p->next[want]==NULL){//如果没有最优匹配的
				if(p->next[1-want]==NULL){//如果都没有,就是到了结尾
					ans=max(ans,get_num^postfix);
					break;
				}else{//有不优匹配
					p=p->next[1-want];
					get_num=get_num*2+1-want;
				}
			}else{//有最优匹配
				p=p->next[want];
				get_num=get_num*2+want;
			}
		}
		ans=max(ans,get_num^postfix);
	}
	cout<<ans<<endl;
	//dealTrie(&root,true);
	return 0;
}
时间: 2024-10-28 21:08:14

CF282 E Sausage Maximization[trie树]的相关文章

Codeforces 282E Sausage Maximization(字典树)

题目链接:282E Sausage Maximization 题目大意:给定一个序列A,要求从中选取一个前缀,一个后缀,可以为空,当时不能重叠,亦或和最大. 解题思路:预处理出前缀后缀亦或和,然后在字典树中维护,每次添加并查询,过程中维护ans. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef lon

codeforces 282E. Sausage Maximization Trie

题目链接 给n个数, 让你找出一个前缀和一个后缀, 它们异或完以后最大, 前缀和后缀都是异或得来的, 可以为空, 为空时按0算.前缀后缀不可覆盖. 这题好神, 竟然是Trie树... 首先将所有数的异或算出来作为初始的后缀, 初始前缀为0. 然后往字典树里插入前缀, 在对后缀进行查找, 查找时, 从高位往低位找, 如果后缀的第i位为0, 那么就找字典树里这一位有没有1, 有1就往1的那一条路找,没有就只能往0那一条路找. 具体看代码. #include <iostream> #include

Codeforces 282E. Sausage Maximization【trie树(非指针版)】

题目大意: 给出一串数,pre[i](前i个数的异或)为a[0]~a[i-1]的异或,post[i](后缀的异或)为a[i]~a[n-1]的异或,求pre[i]^post[j]的最大值(0<=i<=j<=n),其中,pre[0]=0,post[n]=0(表示一个数都不选). 做法: 利用trie树将后缀或者前缀存储起来,首先从pre[n]开始,往前遍历,对于每个前缀,将此时的后缀添加到trie树中,再在trie中寻找与当前前缀异或之后能得到最大的值. 在trie中存储数的时候,将该数的二

poj3630 Phone List (trie树模板题)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26328   Accepted: 7938 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogu

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

Trie树学习2

数组实现的Trie树 字符容量有限,可以使用链表实现更为大容量的Trie #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <map> #include <set> #include <algorithm> #include <cstdlib> #

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]

Trie树

Trie树,即字典树或单词查找树,主要用于大量字符串的检索.去重.排序等操作. 主要原理就是利用字符串的公共前缀建立一棵多叉树,牺牲空间换取时间. 1 //Trie树 2 #include <iostream> 3 #include <string> 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 using std::string; 8 9 const int SIZE = 26; 10 const char B

bzoj4103异或运算 可持久化trie树

要去清华冬令营了,没找到2016年的题,就先坐一坐15年的. 因为n很小,就按照b串建可持久化trie树,a串暴力枚举. 其他的直接看代码. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1,ch=getchar(); while(ch<'0'||ch