CF 655E E. Beautiful Subarrays (ED_12_E)

题意

给你一个大小为n(1 <= n <= 10 ^ 6)的 int 数组,找出连续子串的个数,满足连续子串的亦或值至少为k(1 <= k <= 10 ^ 9)

思路

字典树

代码

#define rep(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, n, m) for (int i = (n); i <= (m); i++)
#define FORD(i, n, m) for (int i = (n); i >= (m); i--)

const int N = 30e6 + 5, L = 30;

int n, m, e, d;
int ch[N][2];
int wv[N];

void init() {
    e = 1, wv[0] = 0;
    ch[0][0] = ch[0][1] = -1;
}

void add(int x) {
    int p = 0, id;
    wv[p]++;
    //sc(x);
    FORD (i, L - 1, 0) {
        id = (x >> i) & 1;
        //sc3(p, id, ch[p][id]);
        if (ch[p][id] == -1) {
            ch[e][0] = ch[e][1] = -1;
            wv[e] = 0;
            ch[p][id] = e++;
        }
        p = ch[p][id], wv[p]++;
        //sc3(p, wv[p], e);
    }
}

int cal() {
    int ans = 0, p = 0, id, x;
    FORD (i, L - 1, 0) {
        id = (m >> i) & 1, x =  (d >> i) & 1 ^ 1;
        if (id) {                   // for bit = 1
            if (ch[p][x] == -1) return ans;
            p = ch[p][x];
        } else {                    // for bit = 0
            if (ch[p][x] != -1) ans += wv[ch[p][x]];
            if (ch[p][x ^ 1] != -1) p = ch[p][x ^ 1];
            else return ans;
        }
    }
    return ans + wv[p];
}

int main() {
    int x;
    LL ans;
    while (~scanf("%d %d", &n, &m)) {
        init();
        ans = 0, d = 0;
        rep (i, n) {
            scanf("%d", &x);
            add(d);
            d ^= x;
            ans += cal();
        }
        cout << ans << '\n';
    }
    return 0;
}

再来个指针版本

#define rep(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, n, m) for (int i = (n); i <= (m); i++)
#define FORD(i, n, m) for (int i = (n); i >= (m); i--)

const int N = 30e6 + 5, L = 30;

struct Node {
    Node *ch[2];
    int val;

    Node() {
        ch[0] = ch[1] = NULL;
        val = 0;
    }

} *root;

int n, m, e, d;

void init() {
    root = new Node();
}

void add(int x) {
    int id;
    Node *p = root;
    p->val ++;
    FORD (i, L - 1, 0) {
        id = (x >> i) & 1;
        if (p->ch[id] == NULL) {
            Node *tmp = new Node();
            p->ch[id] = tmp;
        }
        p = p->ch[id], p->val ++;
    }
}

int cal() {
    int ans = 0, id, x;
    Node *p = root;
    FORD (i, L - 1, 0) {
        id = (m >> i) & 1, x =  (d >> i) & 1 ^ 1;
        if (id) {                   // for bit = 1
            if (p->ch[x] == NULL) return ans;
            p = p->ch[x];
        } else {                    // for bit = 0
            if (p->ch[x] != NULL) ans += p->ch[x]->val;
            if (p->ch[x ^ 1] != NULL) p = p->ch[x ^ 1];
            else return ans;
        }
    }
    return ans + p->val;
}

int main() {
    int x;
    LL ans;
    while (~scanf("%d %d", &n, &m)) {
        init();
        ans = 0, d = 0;
        rep (i, n) {
            scanf("%d", &x);
            add(d);
            d ^= x;
            ans += cal();
        }
        printf("%I64d\n", ans);
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 14,349评论 0 33
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 8,808评论 3 44
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 9,712评论 0 16
  • 【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔...
    叶总韩阅读 10,532评论 0 41
  • 练习了几张水彩卡片的上色,找到了一点感觉。 关于叠色,湿画、干画,调色,有了大概的认识。以后慢慢写出来。 看图: ...
    绾念阅读 3,493评论 0 3