Codeforces 282E Sausage Maximization(字典树)

题目链接:282E Sausage Maximization

题目大意:给定一个序列A,要求从中选取一个前缀,一个后缀,可以为空,当时不能重叠,亦或和最大。

解题思路:预处理出前缀后缀亦或和,然后在字典树中维护,每次添加并查询,过程中维护ans。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;
const int maxn = 1e5 + 5;

struct Tire {
    int sz, g[maxn * 100][2];

    void init();
    void insert(ll s);
    ll find(ll s);
}T;

int N;
ll A[maxn], prefix[maxn], suffix[maxn];

int main () {
    scanf("%d", &N);
    for (int i = 1; i <= N; i++)
        scanf("%lld", &A[i]);

    for (int i = 1; i <= N; i++)
        prefix[i] = prefix[i-1] ^ A[i];
    for (int i = N; i; i--)
        suffix[i] = suffix[i+1] ^ A[i];

    ll ans = 0;
    T.init();

    for (int i = N; i >= 0; i--) {
        T.insert(suffix[i+1]);
        ans = max(ans, T.find(prefix[i]));
    }
    printf("%lld\n", ans);
    return 0;
}

void Tire::init() {
    sz = 1;
    memset(g[0], 0, sizeof(g[0]));
}

void Tire::insert(ll s) {
    int u = 0;

    for (int i = 60; i >= 0; i--) {
        int v = (s>>i)&1;

        if (g[u][v] == 0) {
            memset(g[sz], 0, sizeof(g[sz]));
            g[u][v] = sz++;
        }
        u = g[u][v];
    }
}

ll Tire::find (ll s) {
    int u = 0;
    ll ret = 0;

    for (int i = 60; i >= 0; i--) {
        int v = ((s>>i)&1) ^ 1;

        if (g[u][v])
            ret |= (1LL<<i);
        else
            v = v ^ 1;
        u = g[u][v];
    }
    return ret;
}
时间: 2024-12-25 05:55:42

Codeforces 282E Sausage Maximization(字典树)的相关文章

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中存储数的时候,将该数的二

codeforces 282E. Sausage Maximization Trie

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

Codeforces 948D Perfect Security(字典树)

题目链接:Perfect Security 题意:给出N个数代表密码,再给出N个数代表key.现在要将key组排序,使key组和密码组的亦或所形成的组字典序最小. 题解:要使密码组里面每个数都找到能使其亦或和最小的数可以将key建成一棵字典树(这里建树方式很关键,可以每个数都从2^31开始建树,这样可以使我们在遍历树查询更加方便).之后再遍历密码组每次在字典树里面找到一个能使它亦或和最小的数,再将这个数从字典树中删掉...  字典树太久不写,很多东西都忘记了! 1 #include<bits/s

CodeForces 665E Beautiful Subarrays 字典树

Beautiful Subarrays 题解: 把数字转化成2进制之后,用字典树去维护. 想到字典树之后就应该是一道很容易写的题目了. 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long

CF282 E Sausage Maximization[trie树]

给n个数 求异或前缀(从前连续取一些数全作异或)和异或后缀(从后连续取一些数全作异或)异或的最大值 好坑啊,指针好坑啊 第一道trie树 简单说下解法(其实壳还是不深): 先异或所有数作为初始后缀 然后从前往后的数逐个从后缀出来,进入前缀, 在这个过程中,都把当前前缀变成二进制压入trie,然后当前后缀变成二进制从高位到低位尽量取和它数位不同的值,沿着trie往下走,得到一个最好的数,然后和后缀异或,维护最大值 简直了,指针就是坑 其实还是自己有点坑 说下遇到的坑吧 一开始没有全存64位数(导致

CodeForces 706D Vasiliy&#39;s Multiset (字典树查询+贪心)

题意:最开始的时候有一个集合,集合里面只有一个元素0,现在有q次操作,操作分为3种: + x: 表示向集合中添加一个元素x - x:表示删除集合中值为x的一个元素 ? x:表示查询集合中与x异或的最大值为多少 析:这是一个字典树的应用,不过确实没看出来....主要思想是这样,先用10进制数,转成二进制数,记下每个结点的0,1的个数,这样增加和删除,就是对01的删除, 剩下的就是查询,那么尽量让0和1XOR是最大的,所以,对于给定数,我们要去尽量他的XOR数,如果找到就加上,找不到,就找下一个.这

codeforces 455B A Lot of Games(博弈,字典树)

题目大意:给定n,表示字符串集合.给定k,表示进行了k次游戏,然后是n个字符串.每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手. 解题思路:首先对字符集合建立字典树,然后根据博弈的必胜必败性质搜索出先手的决策状态,可决定胜败3,只能胜利2,只能失败1,不可掌控(即对手可决定胜败)0. 对于状态3,为必胜,可以采用前K-1场败,然后保证第K场自己先手,取必胜方案. 对于状态2,无论则们走都是赢的话,肯定是两个人轮流胜

Codeforces 706D Vasiliy&#39;s Multiset(可持久化字典树)

[题目链接] http://codeforces.com/problemset/problem/706/D [题目大意] 要求实现一个集合中的三个操作,1:在集合中加入一个元素x,2:从集合中删除一个元素x(保证x存在),3:要求从集合中选出一个数,使得其与给出的数x的异或值最大,输出这个异或值. [题解] 可以将所有的以二进制形式存在01字典树上,删除即插入权值为-1的二进制串,对于异或值最大的操作,我们只要在字典树上按位贪心,从最高位开始尽量保证该位存在最后就能得到答案.写代码的时候直接写了

(字典树)codeforces - 706D Vasiliy&#39;s Multiset

原题链接:http://codeforces.com/problemset/problem/706/D 题意:需要你模拟一个多重集合(初始拥有0),该集合拥有三个功能 1.+ x  增加一个x(可以同时存在多个x,因为是多重集合) 2.-  x 去掉一个x 3.? x  输出在这个集合中和x异或最大的值. 分析:有20万个操作,很容易想到树形数据结构,我们可以看到每个x最多只有10^9,而1<<30比10^9大一点,所以10^9次方最多就是29位的01串,可以维护一个字典树. 每个节点有两个分