luogu3373 【模板】线段树2
题目大意:
已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和
本线段树的标记是个二元组:add和mul,其代表将一个线段中的每一个点乘以mul再加add。设区间长度为x,原来区间和为sum。如果两个标记要叠加,标记叠加前区间上的和将是sum*mul+add,叠加后的值将是(sum*mul+add)*mul'+add'=mul*mul'*sum+add*mul'+add'。所以将mul*=mul', add=add*mul'+add'即可。
注意:
- 尽管数据关于P取模了,但是因为有数据相乘的操作,所以程序中所有的值类型都要是long long
- 宏定义ModPlus, ModMult时,如ModMult,不要写成((x%P)*(y%P))%P,应该写成(x*y)%P,否则就被卡常数了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | #include <cstdio> #include <cstring> #include <cassert> using namespace std; const int MAX_RANGE=100010, MAX_NODE = MAX_RANGE * 4; #define LOOP(i, n) for(int i=1; i<=n; i++) long long P, TotRange; long long OrgData[MAX_RANGE]; struct RangeTree { private : #define ModPlus(x, y) ((x)%P+(y)%P)%P #define ModMult(x, y) ((x)%P*(y)%P)%P #define lSon cur*2, l, mid #define rSon cur*2+1, mid+1, r #define Lson cur*2, sl, mid, al, ar #define Rson cur*2+1, mid+1, sr, al, ar struct Tag { long long add, mul; Tag() {} Tag( int m, int a):mul(m),add(a){} void Refresh(Tag x) { mul = ModMult(mul, x.mul); add = ModMult(add, x.mul); add = ModPlus(add, x.add); } void Clear() { add = 0; mul = 1; } int GetSum( int sum, int l, int r) { return ModPlus(ModMult(sum, mul), ModMult(add, (r - l + 1))); } }; Tag _tags[MAX_NODE]; long long Sum[MAX_NODE]; void PushDown( int cur, int l, int r) { if (_tags[cur].add != 0 || _tags[cur].mul != 1) { int mid = (l + r) / 2; Sum[cur * 2] = _tags[cur].GetSum(Sum[cur * 2], l, mid); Sum[cur * 2 + 1] = _tags[cur].GetSum(Sum[cur * 2 + 1], mid + 1, r); _tags[cur * 2].Refresh(_tags[cur]); _tags[cur * 2 + 1].Refresh(_tags[cur]); _tags[cur].Clear(); } } void PullUp( int cur) { Sum[cur] = ModPlus(Sum[cur * 2], Sum[cur * 2 + 1]); } void Update( int cur, int sl, int sr, int al, int ar, int op, int value) { assert (al <= ar && sl <= sr && al <= sr && ar >= sl); if (al <= sl && sr <= ar) { if (op == 1) { Sum[cur] = ModMult(Sum[cur], value); _tags[cur].Refresh(Tag(value, 0)); } else if (op == 2) { Sum[cur] = ModPlus(Sum[cur], (sr - sl + 1)*value); _tags[cur].Refresh(Tag(1, value)); } return ; } PushDown(cur, sl, sr); int mid = (sl + sr) / 2; if (al <= mid) Update(Lson, op, value); if (ar > mid) Update(Rson, op, value); PullUp(cur); } int Query( int cur, int sl, int sr, int al, int ar) { assert (al <= ar && sl <= sr && al <= sr && ar >= sl); if (al <= sl && sr <= ar) return Sum[cur]; PushDown(cur, sl, sr); int mid = (sl + sr) / 2, ans = 0; if (al <= mid) ans = ModPlus(ans, Query(Lson)); if (ar > mid) ans = ModPlus(ans, Query(Rson)); PullUp(cur); return ans; } void SetEachNode( long long *a, int cur, int l, int r) { _tags[cur] = Tag(1, 0); if (l == r) { Sum[cur] = a[l]; return ; } int mid = (l + r) / 2; SetEachNode(a, lSon); SetEachNode(a, rSon); PullUp(cur); } public : RangeTree() {} void SetEachNode( long long *a) { SetEachNode(a, 1, 1, TotRange); } void Update( int l, int r, int op, int value) { Update(1, 1, TotRange, l, r, op, value); } long long Query( int l, int r) { return Query(1, 1, TotRange, l, r); } }g; int main() { int opCnt, op, l, r, val; scanf ( "%lld%d%lld" , &TotRange, &opCnt, &P); LOOP(i, TotRange) scanf ( "%lld" , OrgData + i); g.SetEachNode(OrgData); while (opCnt--) { scanf ( "%d" , &op); switch (op) { case 1: //Mult scanf ( "%d%d%d" , &l, &r, &val); g.Update(l, r, 1, val); break ; case 2: //Plus scanf ( "%d%d%d" , &l, &r, &val); g.Update(l, r, 2, val); break ; case 3: //Query scanf ( "%d%d" , &l, &r); printf ( "%lld\n" , g.Query(l, r)); break ; } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步