洛谷 P5057 [CQOI2006]简单题(树状数组)
生活随笔
收集整理的這篇文章主要介紹了
洛谷 P5057 [CQOI2006]简单题(树状数组)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
嗯...
?
題目鏈接:https://www.luogu.org/problem/P5057
?
首先發現這道題中只有0和1,所以肯定與二進制有關。然后發現這道題需要支持區間更改和單點查詢操作,所以首先想到的是異或意義下的差分數組,于是自己便寫了一個差分數組,確實好寫,但很慢(可能我寫的不優),下面是五十分的異或意義下的差分的代碼:
1 #include<cstdio> 2 #include<iostream> 3 4 using namespace std; 5 6 int a[100005], b[100005]; 7 8 int main(){ 9 int n, m, t, l, r, x; 10 scanf("%d%d", &n, &m); 11 for(int i = 1; i <= n; i++) b[i] = a[i] ^ a[i - 1]; 12 for(int i = 1; i <= m; i++){ 13 scanf("%d", &t); 14 if(t == 1){ 15 scanf("%d%d", &l, &r); 16 b[l] ^= 1; 17 b[r + 1] ^= 1; 18 for(int i = 1; i <= n; i++) 19 a[i] = a[i - 1] ^ b[i]; 20 } 21 else{ 22 scanf("%d", &x); 23 printf("%d\n", a[x]); 24 } 25 } 26 return 0; 27 } 2850分-差分
很明顯,我寫的差分時間復雜度在O(mn)左右,所以超時...
?
而正解是用樹狀數組來維護,因為樹狀數組支持區間更改和單點查詢。注意單點查詢之后,也是本題最神奇的地方,將查詢的10進制%2,即可得它的二進制的最后一位即為答案(也可以理解為進行奇數次操作會改變,進行偶數次操作不會改變)
?
AC代碼:
#include<cstdio> #include<iostream>using namespace std;int n, t[1000005];inline int lowbit(int x){return x & -x; }//lowbit inline void change(int x, int k){while(x <= n){t[x] += k;x += lowbit(x);}return; }//區間更改 inline int check(int x){int ans = 0;while(x > 0){ans += t[x];x -= lowbit(x);}return ans; }//單點查詢int main(){int m, l, r, f, d;scanf("%d%d", &n, &m);for(int i = 1; i <= m; i++){scanf("%d", &f);if(f == 1){scanf("%d%d", &l, &r);change(l, 1);change(r + 1, -1);}else{scanf("%d", &d);printf("%d\n", check(d) % 2);//核心 }}return 0; }AC代碼
?
轉載于:https://www.cnblogs.com/New-ljx/p/11267274.html
總結
以上是生活随笔為你收集整理的洛谷 P5057 [CQOI2006]简单题(树状数组)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑马程序员 交通灯案例
- 下一篇: ios5中apple增加了解析JSON的