P2574 XOR的艺术

线段树的区间修改的修改版

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
int tree[N * 4], mark[N * 4];
char str[N];

void push(int l, int r, int i){
  if(mark[i] % 2 == 0){
    mark[i] = 0;
    return;
  }
  int mid = (l + r) >> 1;
  tree[i * 2] = (mid - l + 1) - tree[i * 2];
  tree[i * 2 + 1] = (r - mid) - tree[i * 2 + 1];
  mark[i * 2] += mark[i];
  mark[i * 2 + 1] += mark[i];
  mark[i] = 0;
}

void build(int l, int r, int i){
  tree[i] = 0;
  if(l == r){
    tree[i] = str[l] - '0';
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, i * 2);
  build(mid + 1, r, i * 2 + 1);
  tree[i] = tree[i * 2] + tree[i * 2 + 1];
}

void changr(int l, int r, int i, int x, int y){
  if(x <= l && y >= r){
    mark[i] ++, tree[i] = (r - l + 1) - tree[i];
    return;
  }
  push(l, r, i);
  int mid = (l + r) >> 1;
  if(mid >= x) changr(l, mid, i * 2, x, y);
  if(mid < y) changr(mid + 1, r, i * 2 + 1, x, y);
  tree[i] = tree[i * 2] + tree[i * 2 + 1];
}

int query(int l, int r, int i, int x, int y){
  int ans = 0;
  if(x <= l && r <= y){
    return tree[i];
  }
  int mid = (l + r) >> 1;
  push(l, r, i);
  if(mid >= x) ans += query(l, mid, i * 2, x, y);
  if(mid < y) ans += query(mid + 1, r, i * 2 + 1, x, y);
  return ans;
}

int main(){
  int n, m;
  scanf("%d%d", &n, &m);
  getchar();
  scanf("%s", str + 1);
  build(1, n, 1);
  while(m --){
    int p, l, r;
    scanf("%d%d%d", &p, &l, &r);
    if(p)
      printf("%d\n", query(1, n, 1, l, r));
    else
      changr(1, n, 1, l, r);
  }
  return 0;
}

posted @ 2022-11-03 21:36  feuerwerk  阅读(28)  评论(0)    收藏  举报