題目連結
題意:
有一字串只包含0和1,然後又m組操作,I L R是將從L到R的字元進行翻轉操作0變為1、1變為0,Q x表示詢問第x的字元。
思路:
我們只需要計算對詢問的字元進行了多少次翻轉,如果是偶數次,該字元變,否則翻轉。對於區間的更新,我們可以使用線段樹,不過對於這個題,因為只是對點的查詢,而且每個節點的初始值都相同,為0,因此我們可以直接使用樹狀數組。下面是一個很巧妙的做法,而且很容易理解。
用了樹狀數組的區間更新 單點尋找(一般為單點更新 區間尋找)
例如 區間(2,4)加1
則Updata(2,1) Updata(4+1,-1)
實現了更新(2,4)的值而不改變其他值
求Sum時即可得到某一點的值
//LA 1080 - Binary Simulation//2013-04-12-18.52#include <stdio.h>#include <string.h>const int maxn = 100010;char str[maxn];int n;int sum[maxn];int lowbit(int x){ return x&(-x);}void change(int x, int v){ while (x <= n) { sum[x] += v; x += lowbit(x); }}int get(int x){ int s = 0; while (x) { s += sum[x]; x -= lowbit(x); } return s;}void update(int l, int r){ change(l, 1); change(r+1, -1);}int main(){ int t, m; scanf("%d",&t); for(int i = 1; i <= t; i++) { memset(sum, 0, sizeof(sum)); scanf("%s",&str[1]); scanf("%d",&m); n =strlen(&str[1]); char op; int l, r; printf("Case %d:\n",i); while (m--) { getchar(); scanf("%c",&op); if (op == 'I') { scanf("%d %d",&l, &r); update(l, r); } else { scanf("%d",&l); if (get(l)%2 == 1) { if (str[l] == '1') puts("0"); else puts("1"); } else printf("%c\n",str[l]); } } } return 0;}
這題也可以用線段樹來做,個人感覺沒有必要,有興趣的讀者可以試試。