线段树区间修改傻题
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 50001
#define root 1, 1, n
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r int n, m, q, res;
int ans[16][N << 2], sum[16][N][2], add[16][N << 2];
char s[N];
//sum[i][j]表示第i列前j个中0的个数 inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline void build(int id, int now, int l, int r)
{
if(l == r)
{
ans[id][now] = sum[id][l][0] - sum[id][l - 1][0];
return;
}
int mid = (l + r) >> 1;
build(id, ls);
build(id, rs);
ans[id][now] = ans[id][now << 1] + ans[id][now << 1 | 1];
} inline void push_down(int id, int now, int l, int r)
{
if(add[id][now] ^ -1)
{
int mid = (l + r) >> 1;
add[id][now << 1] = add[id][now];
add[id][now << 1 | 1] = add[id][now];
ans[id][now << 1] = sum[id][mid][add[id][now]] - sum[id][l - 1][add[id][now]];
ans[id][now << 1 | 1] = sum[id][r][add[id][now]] - sum[id][mid][add[id][now]];
add[id][now] = -1;
}
} inline void update(int id, int now, int l, int r, int x, int y, int c)
{
if(x <= l && r <= y)
{
add[id][now] = c;
ans[id][now] = sum[id][r][c] - sum[id][l - 1][c];
return;
}
push_down(id, now, l, r);
int mid = (l + r) >> 1;
if(x <= mid) update(id, ls, x, y, c);
if(mid < y) update(id, rs, x, y, c);
ans[id][now] = ans[id][now << 1] + ans[id][now << 1 | 1];
} int main()
{
int i, j, r1, r2, c1, c2, x;
n = read();
m = read();
q = read();
for(i = 1; i <= n; i++)
{
scanf("%s", s + 1);
for(j = 1; j <= m; j++)
{
sum[j][i][0] = sum[j][i - 1][0] + (s[j] == '0');
sum[j][i][1] = sum[j][i - 1][1] + (s[j] == '1');
}
}
for(i = 1; i <= m; i++) build(i, root);
memset(add, -1, sizeof(add));
while(q--)
{
r1 = read();
r2 = read();
c1 = read();
c2 = read();
x = read();
res = 0;
for(i = c1; i <= c2; i++)
update(i, root, r1, r2, x);
for(i = 1; i <= m; i++) res += ans[i][1];
printf("%d\n", res);
}
return 0;
}