线段树
以下是一段让人痛苦的代码,其中有挺多的细节,
-
树的大小要开4倍
-
tk指示的是idx以下的子树的更新,不包括子树自己
除此之外,还有最最重要的一点,一定要牢记!!!写代码之前一定要想好怎么写!!!
// author: M@
const int maxn=2e5 + 5;
const int maxm = 2e5 + 5;
const int mod = 100003;
int n,m;
int tree[maxn * 4];
char str[maxn];
bool tk[maxn * 4];
int build(int idx, int l, int r){
if(l == r){
// printf("tree[%d] = %d\n", idx, tree[idx]);
return tree[idx] = str[l] - '0';
}
int mid = (l + r) / 2;
tree[idx] = build(idx<<1, l, mid);
tree[idx] += build(idx<<1|1, mid + 1, r);
// printf("tree[%d] = %d\n", idx, tree[idx]);
return tree[idx];
}
void update(int idx, int len){
if(tk[idx]){
tk[idx] = false;
if(len > 1){
tk[idx<<1] = !tk[idx<<1];
tk[idx<<1|1] = !tk[idx<<1|1];
// tree[idx<<1] = (len / 2) - tree[idx<<1];
// tree[idx<<1|1] = len - (len / 2) - tree[idx<<1|1];
tree[idx<<1] = len - (len / 2) - tree[idx<<1];
tree[idx<<1|1] =(len / 2) - tree[idx<<1|1];
}
}
}
int push_down(int idx, int l, int r, int tl, int tr){
int li = idx<<1, ri = idx<<1|1;
if(l == tl && r == tr){
tk[idx] = !tk[idx];
tree[idx] = r - l + 1 - tree[idx];
update(idx, r - l + 1);
// printf("%d %d %d %d %d tree[idx] %d\n", idx, l, r, tl, tr, tree[idx]);
return tree[idx];
}
int mid = (l + r) / 2;
update(idx, r - l + 1);
if(mid >= tl)push_down(li, l, mid, tl, min(tr, mid));
if(mid < tr)push_down(ri, mid + 1, r, max(tl, mid + 1), tr);
tree[idx] = tree[li] + tree[ri];
// printf("%d %d %d %d %d tree[idx] %d\n", idx, l, r, tl, tr, tree[idx]);
return tree[idx];
}
int query(int idx, int l, int r, int tl, int tr){
int li = idx<<1, ri = idx<<1|1;
update(idx, r - l + 1);
if(l == tl && r == tr){
// printf("%d %d %d %d %d tree[idx] %d\n", idx, l, r, tl, tr, tree[idx]);
return tree[idx];
}
int mid = (l + r) / 2;
int ans = 0;
if(mid >= tl)ans += query(idx<<1, l, mid, tl, min(tr, mid));
if(mid < tr)ans += query(idx<<1|1, mid + 1, r, max(tl, mid + 1), tr);
// printf("%d %d %d %d %d tree[idx] %d\n", idx, l, r, tl, tr, tree[idx]);
return ans;
}
int main()
{
#ifdef m_
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
scanf("%d%d", &n, &m);
scanf("%s", str + 1);
build(1, 1, n);
// cout<<"sss"<<endl;
while(m--){
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
// printf("\nop %d %d %d\n", op, l, r);
if(op == 0){
push_down(1, 1, n, l, r);
}
else{
printf("%d\n", query(1, 1, n, l, r));
}
// puts("");
}
#ifdef m_
fclose(stdin);
// fclose(stdout);
#endif
return 0;
}
https://blog.csdn.net/zearot/article/details/48299459