LightOJ 1269 Consecutive Sum(字典树)

来源:互联网 发布:上瘾网络剧见面会 编辑:程序博客网 时间:2024/04/29 04:47

题意:

给定一个序列,求选定一段区间的亦或和最大值和最小值。

解析:

由于是区间问题,很容易就能想到是要先求前缀异或和。
可以对所有前缀和建立字典树,节点的末尾保存二进制转化成十进制的值。
先查询,再插入。
可以先将所有的的数字转化成二进制字符串,高位在前,低位在后。
最大值很简单,查找时然后尽量往反向走;
最小则需要尽量往正向走。
知道走到尽头时把找到的十进制,异或上当前的值。

my code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int MAXN = 50005;const int maxnode = MAXN * 33;const int sigma_size = 2;const int INF = (1LL << 31) - 1;struct Trie {    int ch[maxnode][sigma_size];    int val[maxnode];    int sz;    void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }    Trie() { clear(); }    int idx(char c) { return c - '0'; }    void insert(char *s, int v) {        int u = 0, n = strlen(s);        for(int i = 0; i < n; i++) {            int c = idx(s[i]);            if(!ch[u][c]) {                memset(ch[sz], 0, sizeof(ch[sz]));                val[u] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        val[u] = v;    }    //^0 equal    //^1 opposite    int find(char *s, int value, int dir) {        int u = 0, n = strlen(s);           for(int i = 0; i < n; i++) {            int c = idx(s[i]);            int v = c ^ dir;            if(!ch[u][v])                v ^= 1;            u = ch[u][v];        }        return val[u] ^ value;    }} trie;int n, sum[MAXN], A[MAXN];char bit[33];void trans(char *s, int v) {    for(int i = 31; i >= 0; i--)        s[i] = ((v >> i) & 1) + '0';    s[32] = '\0';    reverse(s, s+32);}int main() {    int T, cas = 1;    scanf("%d", &T);    while(T--) {        scanf("%d", &n);        trie.clear();        sum[0] = 0;        for(int i = 1; i <= n; i++) {            scanf("%d", &A[i]);            sum[i] = sum[i-1] ^ A[i];        }        trans(bit, 0);        trie.insert(bit, 0);        int maxv = -INF, minv = INF;        int mx, mi;        for(int i = 1; i <= n; i++) {            trans(bit, sum[i]);            mi = trie.find(bit, sum[i], 0);            mx = trie.find(bit, sum[i], 1);            minv = min(mi, minv);            maxv = max(mx, maxv);            trie.insert(bit, sum[i]);        }        printf("Case %d: %d %d\n", cas++ , maxv, minv);    }    return 0;}
0 0
原创粉丝点击