zwei
模拟9 T2
(COGS上也有,链接http://218.28.19.228/cogs/problem/problem.php?pid=1427)
题目描述
维护一个数组a[i],支持两个操作,数组从1开始下标。
1. 将a[x]修改成y。
2. 求l到r之间所有数的异或和。
分析
这个接近于裸题了,线段树树状数组什么的随意。(其实经亲测,在COGS上暴力都能过,但<老师电脑上的>cena过不了)
知道0⊕b = b, a⊕b⊕a = b,就差不多了。
ps:顺便说一句,从这道题开始,突然就爱上了打DP,AC率那真是瞬间大了好多。
这个是用线段树写的:
1 /************************************************** 2 Origin: Simulation 9 Problem 2 3 Author: Xue Zhonghao 4 Data: 2014-4-9 19:59:24 5 State: Accepted 6 **************************************************/ 7 #include<cstdio> 8 #include<fstream> 9 using namespace std; 10 ifstream fin("zwei.in"); 11 ofstream fout("zwei.out"); 12 13 #define MAXN 300010 14 15 int tr[MAXN][3]; 16 17 void read(int root, int l, int r) { 18 tr[root][0] = l; 19 tr[root][1] = r; 20 if(l == r) { fin>>tr[root][2]; return; } 21 int k = (l + r) / 2; 22 read(root<<1, l, k); 23 read((root<<1)+1, k+1, r); 24 tr[root][2] = tr[root<<1][2] ^ tr[(root<<1)+1][2]; 25 } 26 27 int change(int root, int k, int x) { 28 int ans; 29 if(tr[root][0] == tr[root][1]) { 30 ans = x ^ tr[root][2]; 31 tr[root][2] = x; 32 return ans; 33 } 34 int p = (tr[root][0] + tr[root][1]) / 2; 35 if(p < k) ans = change((root<<1)+1, k, x); 36 else ans = change(root<<1, k, x); 37 tr[root][2] ^= ans; 38 return ans; 39 } 40 41 int ques(int root, int l, int r) { 42 if(tr[root][0] >= l && tr[root][1] <= r) return tr[root][2]; 43 int ans = 0, k = (tr[root][0] + tr[root][1]) / 2; 44 if(r >= tr[root][0] && l <= k) ans ^= ques(root<<1, l, r); 45 if(r >= k && l <= tr[root][1]) ans ^= ques((root<<1)+1, l, r); 46 return ans; 47 } 48 49 int main(void) 50 { 51 int N, M; 52 int k, x, y; 53 int ans; 54 fin>>N>>M; 55 read(1, 1, N); 56 //for(int i = 1; i <= 9; ++i) fout<<tr[i][2]<<" "; 57 for(int i = 0; i < M; ++i) { 58 fin>>k>>x>>y; 59 if(k) { 60 ans = ques(1, x, y); 61 fout<<ans<<endl; 62 } 63 else change(1, x, y); 64 } 65 return 0; 66 }