CF665E Beautiful Subarrays字典树


题意:求n个非负整数的数组有多少个子区间,满足区间的异或和至少是K。


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new CF665E().solve();
	}
}

class CF665E {

	InputReader in = new InputReader(System.in);
	PrintWriter out = new PrintWriter(System.out);
	
	Trie tree = new Trie() ;

	void solve() {
		int n = in.nextInt() ;
		int k = in.nextInt() ;
		long res = 0 ;
		tree.clear() ; 
		tree.add(0) ;
		int now = 0 ; 
		for(int i = 0 ; i < n ; i++){
			now ^= in.nextInt() ;
			res += tree.find(now , k) ;
			tree.add(now) ;
		}
        out.println(res) ;
        out.flush() ;
	}
}

class Trie{
	
	final int NODESIZE = 1000001*30 ;
	final int NULL = 0 ;
	int root ;
	int totel ; 
	int[][] next = new int[2][NODESIZE] ;
	int[] cnt = new int[NODESIZE] ;
	
	int newNode(){
		next[0][totel] = next[1][totel] = NULL ;
		cnt[totel] = 0 ;
        return totel++ ; 		
	}
	
	void clear(){
		totel = 0 ;
		root = newNode() ;
	}
	
	void add(int x){
		int now = root ;
		for(int i = 30 ; i >= 0 ; i--){
			int son = ( x & (1<<i) ) > 0 ? 1 : 0 ;
			if(next[son][now] == NULL)
				next[son][now] = newNode() ;
			now = next[son][now] ;
			cnt[now]++ ;
		}
	}
	
	int find(int x , int k){
		int res = 0 ;
		int now = root ;
		for(int i = 30 ; i >= 0 ; i--){
			int bitX = ( x & (1<<i) ) > 0 ? 1 : 0 ;
			int bitK = ( k & (1<<i) ) > 0 ? 1 : 0 ;
			if(bitX == 1 && bitK == 1){
				if(next[0][now] == NULL) return res ;
				else now = next[0][now] ;
			}
			else if(bitX == 0 && bitK == 1){
				if(next[1][now] == NULL) return res ;
				else now = next[1][now] ;
			}
			else if(bitX == 1 && bitK == 0){
				if(next[0][now] != NULL) res += cnt[next[0][now]] ;
				if(next[1][now] == NULL) return res ;
				else now = next[1][now] ;
			}
			else if(bitX == 0 && bitK == 0){
				if(next[1][now] != NULL) res += cnt[next[1][now]] ;
				if(next[0][now] == NULL) return res ;
				else now = next[0][now] ;
			}
		}
		return res + cnt[now] ;
	}

}

class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值