1. 程式人生 > >Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(離線樹狀數組)

Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(離線樹狀數組)

turn string 之前 algorithm printf ace r++ void contest

http://codeforces.com/contest/703/problem/D

題意:

給出一行數,有m次查詢,每次查詢輸出區間內出現次數為偶數次的數字的異或和。

思路:

這兒利用一下異或和的性質,在一個區間中,我們如果把所有數字都異或的話,可以發現最後偶數次的數字異或後都變成了0,只剩下了奇數次的數字異或。

舉個例子,{1,2,3,2,3,5}

異或和是1^2^3^2^3^5=1^5

因為最後要計算偶數次數字的異或和,那麽最後我們只需要再異或上該區間內所有不同數字即可。

那麽我們可以先計算出前綴異或和,之後就只要求區間上的不同數字的異或和即可。

離線樹狀數組和在線樹狀數組的不同點是前者是先把所有詢問存儲下來,排序後再處理。

拿這道題目來說,我們將詢問按照右端點從小到大排序,然後依次計算詢問,如果當前數字在之前已經出現過,那麽就先刪去它,然後再插入該數字,這樣就保證了這個區間內不同的數字只出現一次,具體可見代碼。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<string>
 6 #include<vector>
 7 #include<queue>
 8 #include<cmath>
 9
#include<map> 10 using namespace std; 11 typedef long long LL; 12 13 const int maxn=1e6+5; 14 15 struct node 16 { 17 int l,r; 18 int id; 19 }q[maxn]; 20 21 map<int,int> pos; 22 23 int n,m; 24 int a[maxn]; 25 int c[maxn]; 26 int sum[maxn]; 27 int pre[maxn]; 28
LL ans[maxn]; 29 30 bool cmp(node a,node b) 31 { 32 return a.r<b.r||(a.r==b.r && a.l<b.l); 33 } 34 35 int lowbit(int x) 36 { 37 return x&-x; 38 } 39 40 int XOR_sum(int x) 41 { 42 int ret=0; 43 while(x>0) 44 { 45 ret^=c[x]; 46 x-=lowbit(x); 47 } 48 return ret; 49 } 50 51 void add(int x,int d) 52 { 53 while(x<=maxn) 54 { 55 c[x]^=d; 56 x+=lowbit(x); 57 } 58 } 59 60 int main() 61 { 62 //freopen("D:\\input.txt","r",stdin); 63 while(~scanf("%d",&n)) 64 { 65 pos.clear(); 66 sum[0]=0; 67 for(int i=1;i<=n;i++) 68 { 69 scanf("%d",&a[i]); 70 sum[i]=sum[i-1]^a[i]; 71 pre[i]=pos[a[i]]; //記錄a[i]這個數前面出現的位置 72 pos[a[i]]=i; //更新a[i]最晚的出現位置 73 } 74 scanf("%d",&m); 75 for(int i=0;i<m;i++) 76 { 77 scanf("%d%d",&q[i].l,&q[i].r); 78 q[i].id=i; 79 } 80 sort(q,q+m,cmp); 81 memset(c,0,sizeof(c)); 82 for(int i=0,r=1;i<m;i++) 83 { 84 while(r<=q[i].r) 85 { 86 if(pre[r]) //如果第r個位置的數之前已經出現過,就刪去這個數 87 add(pre[r],a[r]); 88 add(r,a[r]); //添加第r個數 89 r++; 90 } 91 ans[q[i].id]=XOR_sum(q[i].r)^XOR_sum(q[i].l-1)^sum[q[i].r]^sum[q[i].l-1]; 92 } 93 for(int i=0;i<m;i++) 94 printf("%I64d\n",ans[i]); 95 } 96 return 0; 97 }

Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(離線樹狀數組)