1. 程式人生 > >CodeForces E. XOR and Favorite Number(Div.2)

CodeForces E. XOR and Favorite Number(Div.2)

題解

一個莫隊的基礎題,題目要求[L,R]裡面有多少對子區間異或值為k,記錄一下字首異或和arr,因為xx=0,現在我們要求區間[L,R]的異或和值,用arr陣列表示就是arr[L-1]arr[R]=k,或者說arr[R]^k=arr[L-1]

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
	
	final static int N = 1 << 21;
	static
long nowAns = 0;//當前答案 static int n,m,k,block; static long[] cnt = new long[N];//每個數出現的次數 static long[] ans = new long[N];//記錄每個答案 static int[] arr = new int[N];//字首異或和 static Query[] q = new Query[N];//詢問 public static class cmp implements Comparator<Query> { public int compare(Query x,Query y)
{ if(x.l / block == y.l / block) return x.r - y.r; return x.l / block - y.l / block; } } public static void remove(int x) { cnt[arr[x]]--; nowAns -= cnt[arr[x] ^ k]; } public static void add(int x) { nowAns += cnt[arr[x] ^ k]; cnt[arr[x]]++; } public static void
main(String[] args) { Scanner cin = new Scanner(new BufferedInputStream(System.in)); int l = 1,r = 0; n = cin.nextInt();//陣列長度 m = cin.nextInt();//詢問次數 k = cin.nextInt(); block = (int) Math.sqrt(n);//每塊的大小 for(int i = 1;i <= n;i++) { int tmp = cin.nextInt(); arr[i] = arr[i - 1] ^ tmp; } for(int i = 1;i <= m;i++) { int tmp_l = cin.nextInt(); int tmp_r = cin.nextInt(); q[i] = new Query(tmp_l,tmp_r,i);//減1是為了將詢問轉換為下標 } Arrays.sort(q,1,m + 1,new cmp());//sort是左閉右開的區間 cnt[0] = 1; for(int i = 1;i <= m;i++) { while(l < q[i].l) { remove(l - 1);//移出數字 l++; } while(l > q[i].l) { l--; add(l - 1);//加入數字 } while(r < q[i].r) add(++r);//加入數字 while(r > q[i].r) remove(r--);//移出數字 ans[q[i].id] = nowAns; } for(int i = 1;i <= m;i++) System.out.println(ans[i]); } } class Query { int l,r,id; Query(int L,int R,int id) { this.l = L; this.r = R; this.id = id; } }