zoukankan      html  css  js  c++  java
  • CodeForces 665E Beautiful Subarrays

    题目

    传送门

    解法

    \(a\) 序列做一个异或前缀和,我们就将问题转化为查询一个数与 \(\mathtt{trie}\) 树内数字异或值 \(\ge k\) 的个数。

    比如设当前询问的前缀和为 \(x\)

    • \(k\)\(i\) 位是 \(0\):如果这一位选择 \(x[i]\oplus 1\) 的方向,这一位异或的答案会是 \(1\),那么在这之后的所有情况一定都是合法的,我们直接累加,跳过即可。然后选择 \(x[i]\) 这个方向。
    • \(k\)\(i\) 位是 \(1\):我们只能使异或答案为 \(1\)。选择 \(x[i]\oplus 1\) 的方向。

    注意需要提前插入 \(0\)

    代码

    #include<cstdio>
    
    const int N = (1 << 24) + 2;
    
    int n, k, sum, ch[N][2], siz[N], cnt = 1; 
    long long ans;
    
    int read() {
    	int x = 0, f = 1; char s;
    	while((s = getchar()) > '9' || s < '0') {if(s == '-') f = -1;}
    	while(s <= '9' && s >= '0') {
    		x = (x << 1) + (x << 3) + (s ^ 48);
    		s = getchar();
    	}
    	return x * f;
    }
    
    void insert(const int x) {
    	int p = 1;
    	for(int i = 30; i >= 0; -- i)  {
    		int op = (x >> i) & 1;
    		if(! ch[p][op]) ch[p][op] = ++ cnt;
    		++ siz[p]; p = ch[p][op];                 
    	}
    	++ siz[p];
    }
    
    void ask(const int x) {
    	int p = 1;
    	for(int i = 30; i >= 0; -- i) {
    		int op = (x >> i) & 1;
    		if(! ((k >> i) & 1)) ans += siz[ch[p][op ^ 1]], p = ch[p][op];
    		else p = ch[p][op ^ 1];
    	}
    	ans += siz[p];
    }
    
    int main() {
    	n = read(), k = read();
    	insert(0);
    	for(int i = 1; i <= n; ++ i) {
    		sum ^= read();
    		ask(sum); insert(sum);
    	}
    	printf("%lld\n", ans);
    	return 0;
    }
    
  • 相关阅读:
    EXTJS 动态改变Gird 列值
    EXTJS动态改变store的proxy的params
    获取Spring容器Bean
    EXTJS 6 必填项加星号*
    Maven打包附加配置文件
    MyEclipse 优化
    Android-SurfaceView生命周期
    Android-PopupWindow
    Android-Sqlite3的使用
    Android-adb的使用
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/12348795.html
Copyright © 2011-2022 走看看