二次联通门 : codevs 4919 线段树练习4
/* codevs 4919 线段树练习4 线段树 每个点中维护mod 7余数的个数 每次利用临时数组res把原来的余数存下来 区间修改时把所要加的数mod7后加上当前的余数即为所求的余数 后进行转换... (我知道自己说的很迷..但是自己稍微想想就好了) */ #include <cstdio> #define Mod 7 #define Max 100090 void read (int &now) { now = 0; register char word = getchar (); bool flag = false; while (word < '0' || word > '9') { if (word == '-') flag = true; word = getchar (); } while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } if (flag) now = -now; } struct Segment_Tree { struct Segment { int l; int r; int number[7]; int Ruri; int Mid; }; int x; Segment tree[Max << 3]; Segment *L, *R; void Build (int l, int r, int now) { tree[now].l = l; tree[now].r = r; if (l == r) { read (x); tree[now].number[x % Mod]++; return ; } tree[now].Mid = (l + r) >> 1; Build (l, tree[now].Mid, now << 1); Build (tree[now].Mid + 1, r, now << 1 | 1); for (int i = 0; i <= 6; i++) tree[now].number[i] = tree[now << 1].number[i] + tree[now << 1 | 1].number[i]; } int res[7]; void Change_section (int l, int r, int now, int to) { if (tree[now].l == l && tree[now].r == r) { for (int i = 0; i <= 6; i++) res[i] = tree[now].number[i]; for (int i = 0; i <= 6; i++) tree[now].number[(i + to) % Mod] = res[i]; tree[now].Ruri += to; return ; } if (tree[now].Ruri) { L = &tree[now << 1]; R = &tree[now << 1 | 1]; for (int i = 0; i <= 6; i++) res[i] = L->number[i]; for (int i = 0; i <= 6; i++) L->number[(i + tree[now].Ruri) % Mod] = res[i]; for (int i = 0; i <= 6; i++) res[i] = R->number[i]; for (int i = 0; i <= 6; i++) R->number[(i + tree[now].Ruri) % Mod] = res[i]; L->Ruri += tree[now].Ruri; R->Ruri += tree[now].Ruri; tree[now].Ruri = 0; } if (r <= tree[now].Mid) Change_section (l, r, now << 1, to); else if (l > tree[now].Mid) Change_section (l, r, now << 1 | 1, to); else { Change_section (l, tree[now].Mid, now << 1, to); Change_section (tree[now].Mid + 1, r, now << 1 | 1, to); } for (int i = 0; i <= 6; i++) tree[now].number[i] = tree[now << 1].number[i] + tree[now << 1 | 1].number[i]; } int Query_section_count (int l, int r, int now) { if (tree[now].l == l && tree[now].r == r) return tree[now].number[0]; if (tree[now].Ruri) { L = &tree[now << 1]; R = &tree[now << 1 | 1]; for (int i = 0; i <= 6; i++) res[i] = L->number[i]; for (int i = 0; i <= 6; i++) L->number[(i + tree[now].Ruri) % Mod] = res[i]; for (int i = 0; i <= 6; i++) res[i] = R->number[i]; for (int i = 0; i <= 6; i++) R->number[(i + tree[now].Ruri) % Mod] = res[i]; L->Ruri += tree[now].Ruri; R->Ruri += tree[now].Ruri; tree[now].Ruri = 0; } if (r <= tree[now].Mid) return Query_section_count (l, r, now << 1); else if (l > tree[now].Mid) return Query_section_count (l, r, now << 1 | 1); else return Query_section_count (l, tree[now].Mid, now << 1) + Query_section_count (tree[now].Mid + 1, r, now << 1 | 1); for (int i = 0; i <= 6; i++) tree[now].number[i] = tree[now << 1].number[i] + tree[now << 1 | 1].number[i]; } }; Segment_Tree Tree; int N; int main (int argc, char *argv[]) { register char type[7]; read (N); Tree.Build (1, N, 1); read (N); int x, y, z; while (N--) { scanf ("%s", type); read (x); read (y); if (type[0] == 'c') printf ("%d ", Tree.Query_section_count (x, y, 1)); else { read (z); Tree.Change_section (x, y, 1, z); } } return 0; }