luogu P3373 【模板】线段树 2
二次联通门 : luogu P3373 【模板】线段树 2
/* P3373 线段树 2 此题的难点(雾)在于标记下放的顺序 问题主要是没法分断是先乘还是先加 一般的解决方法是把乘法变成加法。 1:s*lazy+flag. 2:(s+flag)*lazy=s*lazy+flag*lazy. */ #include <iostream> #include <cstring> #include <cstdio> #define Max 100005 using namespace std; typedef long long LL; void read (LL &now) { now = 0; char word = getchar (); bool temp = false; while (word < '0' || word > '9') { if (word == '-') temp = true; word = getchar (); } while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } if (temp) now = -now; } void write (LL now) { char word[20]; int Len = 0; if (now == 0) putchar ('0'); if (now < 0) { putchar ('-'); now = -now; } while (now) { word[++Len] = now % 10; now /= 10; } while (Len--) putchar (word[Len + 1] + '0'); } struct Tree { LL l; LL r; LL Sum; LL Mul_flag; LL Add_flag; bool flag; }tree[Max << 2]; LL M, N, Mod; Tree *res, *L, *R; void Tree_Build (LL l, LL r, LL now) { tree[now].l = l; tree[now].r = r; if (l == r) { scanf ("%lld", &tree[now].Sum); return ; } LL Mid = (l + r) >> 1; Tree_Build (l, Mid, now << 1); Tree_Build (Mid + 1, r, now << 1 | 1); tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod; } void Tree_Add (LL l, LL r, LL now, LL to) { if (tree[now].l == l && tree[now].r == r) { tree[now].Add_flag = (tree[now].Add_flag + to) % Mod; tree[now].Sum = (tree[now].Sum + ((r - l + 1) * to)) % Mod; return ; } if (tree[now].Add_flag || tree[now].flag) { res = &tree[now]; L = &tree[now << 1]; R = &tree[now << 1 | 1]; if (res->flag) { L->Sum = (L->Sum * res->Mul_flag) % Mod; R->Sum = (R->Sum * res->Mul_flag) % Mod; L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod; R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod; if (L->flag) L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod; else { L->Mul_flag = res->Mul_flag; L->flag = true; } if (R->flag) R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod; else { R->Mul_flag = res->Mul_flag; R->flag = true; } res->flag = false; } if (res->Add_flag) { L->Add_flag = (L->Add_flag + res->Add_flag) % Mod; R->Add_flag = (R->Add_flag + res->Add_flag) % Mod; L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod; R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod; res->Add_flag = 0; } } LL Mid = (tree[now].l + tree[now].r) >> 1; if (r <= Mid) Tree_Add (l, r, now << 1, to); else if (l > Mid) Tree_Add (l, r, now << 1 | 1, to); else { Tree_Add (l, Mid, now << 1, to); Tree_Add (Mid + 1, r, now << 1 | 1, to); } tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod; } void Tree_Mul (LL l, LL r, LL now, LL to) { if (tree[now].l == l && tree[now].r == r) { tree[now].Sum = (tree[now].Sum * to) % Mod; tree[now].Add_flag = (tree[now].Add_flag * to) % Mod; if (tree[now].flag) tree[now].Mul_flag = (tree[now].Mul_flag * to) % Mod; else { tree[now].flag = true; tree[now].Mul_flag = to; } return ; } if (tree[now].Add_flag || tree[now].flag) { res = &tree[now]; L = &tree[now << 1]; R = &tree[now << 1 | 1]; if (res->flag) { L->Sum = (L->Sum * res->Mul_flag) % Mod; R->Sum = (R->Sum * res->Mul_flag) % Mod; L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod; R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod; if (L->flag) L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod; else { L->Mul_flag = res->Mul_flag; L->flag = true; } if (R->flag) R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod; else { R->Mul_flag = res->Mul_flag; R->flag = true; } res->flag = false; } if (res->Add_flag) { L->Add_flag = (L->Add_flag + res->Add_flag) % Mod; R->Add_flag = (R->Add_flag + res->Add_flag) % Mod; L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod; R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod; res->Add_flag = 0; } } LL Mid = (tree[now].l + tree[now].r) >> 1; if (r <= Mid) Tree_Mul (l, r, now << 1, to); else if (l > Mid) Tree_Mul (l, r, now << 1 | 1, to); else { Tree_Mul (l, Mid, now << 1, to); Tree_Mul (Mid + 1, r, now << 1 | 1, to); } tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod; } LL Tree_Query (LL l, LL r, LL now) { if (tree[now].l == l && tree[now].r == r) return tree[now].Sum % Mod; if (tree[now].Add_flag || tree[now].flag) { res = &tree[now]; L = &tree[now << 1]; R = &tree[now << 1 | 1]; if (res->flag) { L->Sum = (L->Sum * res->Mul_flag) % Mod; R->Sum = (R->Sum * res->Mul_flag) % Mod; L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod; R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod; if (L->flag) L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod; else { L->Mul_flag = res->Mul_flag; L->flag = true; } if (R->flag) R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod; else { R->Mul_flag = res->Mul_flag; R->flag = true; } res->flag = false; } if (res->Add_flag) { L->Add_flag = (L->Add_flag + res->Add_flag) % Mod; R->Add_flag = (R->Add_flag + res->Add_flag) % Mod; L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod; R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod; res->Add_flag = 0; } } tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod; LL Mid = (tree[now].l + tree[now].r) >> 1; if (r <= Mid) return Tree_Query (l, r, now << 1) % Mod; else if (l > Mid) return Tree_Query (l, r, now << 1 | 1) % Mod; else return (Tree_Query (l, Mid, now << 1) + Tree_Query (Mid + 1, r, now << 1 | 1)) % Mod; } int main (int argc, char *argv[]) { read (N); read (M); read (Mod); Tree_Build (1, N, 1); LL type; LL l, r, z; for (int i = 1; i <= M; i++) { read (type); read (l); read (r); switch (type) { case 1: { read (z); Tree_Mul (l, r, 1, z); break; } case 2: { read (z); Tree_Add (l, r, 1, z); break; } case 3: { write (Tree_Query (l, r, 1)); putchar ('\n'); break; } } } return 0; }
myj 吊打我Orz,xxy 捆起来打我Orz,myl 文化课上天Orz, lrh 姿势水平敲高Orz, hkd 特别胖Orz%%%,cys 智商感人Orz,syl zz专业Orz,我没有学上, 我们未来一片光明