P3373 【模板】线段树 2

P3373 【模板】线段树 2

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5+5;
 5 ll a[maxn], add[maxn*4], mul[maxn*4], sum[maxn*4];
 6 ll n, m, p;
 7 void pushup(int rt) {
 8     sum[rt] = (sum[rt*2]+sum[rt*2+1])%p;
 9 }
10 void pushdown(int rt, int l, int r) {
11     int mid = (l+r)/2;
12     sum[rt*2] = (sum[rt*2]*mul[rt]+add[rt]*(mid-l+1))%p;
13     sum[rt*2+1] = (sum[rt*2+1]*mul[rt]+add[rt]*(r-mid))%p;
14     mul[rt*2] = (mul[rt*2]*mul[rt])%p;
15     mul[rt*2+1] = (mul[rt*2+1]*mul[rt])%p;
16     add[rt*2] = (add[rt*2]*mul[rt]+add[rt])%p;
17     add[rt*2+1] = (add[rt*2+1]*mul[rt]+add[rt])%p;
18 
19     mul[rt] = 1;
20     add[rt] = 0;
21 }
22 void build(int l, int r, int rt) {
23     add[rt] = 0;
24     mul[rt] = 1;
25     if (l == r) {
26         sum[rt] = a[l]%p;
27         return;
28     }
29     int mid = (l+r)/2;
30     build(l,mid,rt*2);
31     build(mid+1,r,rt*2+1);
32     pushup(rt);
33 }
34 void update1(int be, int ed, int val, int l, int r, int rt) {
35     if (be <= l && r <= ed) {
36         add[rt] = (add[rt]*val)%p;
37         mul[rt] = (mul[rt]*val)%p;
38         sum[rt] = (sum[rt]*val)%p;
39         return;
40     }
41     pushdown(rt,l,r);
42     int mid = (l+r)/2;
43     if (be <= mid) update1(be,ed,val,l,mid,rt*2);
44     if (ed > mid) update1(be,ed,val,mid+1,r,rt*2+1);
45     pushup(rt);
46 }
47 void update2(int be, int ed, int val, int l, int r, int rt) {
48     if (be <= l && r <= ed) {
49         add[rt] = (add[rt]+val)%p;
50         sum[rt] = (sum[rt]+val*(r-l+1))%p;
51         return;
52     }
53     pushdown(rt,l,r);
54     int mid = (l+r)/2;
55     if (be <= mid) update2(be,ed,val,l,mid,rt*2);
56     if (ed > mid) update2(be,ed,val,mid+1,r,rt*2+1);
57     pushup(rt);
58 }
59 ll query(int be, int ed, int l, int r, int rt) {
60     if (be <= l && r <= ed) {
61         return sum[rt];
62     }
63     pushdown(rt,l,r);
64     ll res = 0; int mid = (l+r)/2;
65     if (be <= mid) res = (res+query(be,ed,l,mid,rt*2))%p;
66     if (ed > mid) res = (res+query(be,ed,mid+1,r,rt*2+1))%p;
67     return res;
68 }
69 int main() {
70     scanf("%d%d",&n,&m); scanf("%lld",&p);
71     for (int i = 1; i <= n; i++) scanf("%lld",&a[i]);
72     build(1,n,1);
73     while (m--) {
74         int op, x, y; scanf("%d%d%d",&op,&x,&y);
75         if (op == 1) {
76             int k; scanf("%d",&k);
77             update1(x,y,k,1,n,1);
78         }
79         else if (op == 2) {
80             int k; scanf("%d",&k);
81             update2(x,y,k,1,n,1);
82         }
83         else {
84             ll ans = query(x,y,1,n,1);
85             printf("%lld\n",ans);
86         }
87     }
88     return 0;
89 }

 

分块,学习了各种玄学卡常数的操作

  1 #include <bits/stdc++.h>
  2 #define rg register
  3 using namespace std;
  4 typedef long long ll;
  5 const int maxn = 1e5+5;
  6 char buf[70000000];
  7 int n, m, cnt = 0;
  8 int pos[maxn], L[maxn], R[maxn];
  9 ll a[maxn], add[maxn], mul[maxn], sum[maxn];
 10 ll block, val, mod;
 11 template<typename T> inline T read(T a) {
 12     T res = 0, f = 1;
 13     char ch = buf[cnt++];
 14     while (!isdigit(ch)) {
 15         if (ch == '-') f = -1;
 16         ch = buf[cnt++];
 17     }
 18     while (isdigit(ch)) {
 19         res = (res<<3)+(res<<1)+ch-48;
 20         ch = buf[cnt++];
 21     }
 22     return res*f;
 23 }
 24 template<typename T> inline void write(T x) {
 25     if (x < 0) {
 26         putchar('-');
 27         write(-x);
 28         return;
 29     }
 30     if (x > 9) write(x/10);
 31     putchar(x%10+48);
 32 }
 33 inline void reset(int x) {
 34     for (int i = L[x]; i <= R[x]; ++i)
 35         a[i] = (a[i]*mul[x]+add[x])%mod;
 36     add[x] = 0, mul[x] = 1;
 37 }
 38 inline void Add(int l, int r, ll val) {
 39     int p = pos[l], q = pos[r];
 40     if (p == q) {
 41         reset(p);
 42         sum[p] = (sum[p]+(r-l+1)*val)%mod;
 43         for (int i = l; i <= r; ++i)
 44             a[i] += val;
 45     }
 46     else {
 47         reset(p);
 48         sum[p] = (sum[p]+(R[p]-l+1)*val)%mod;
 49         for (int i = l; i <= R[p]; ++i)
 50             a[i] += val;
 51 
 52         reset(q);
 53         sum[q] = (sum[q]+(r-L[q]+1)*val)%mod;
 54         for (int i = L[q]; i <= r; ++i)
 55             a[i] += val;
 56 
 57         for (int i = p+1; i <= q-1; ++i) {
 58             add[i] += val;
 59             sum[i] = (sum[i]+block*val)%mod;
 60         }
 61     }
 62 }
 63 inline void Mul(int l, int r, ll val) {
 64     int p = pos[l], q = pos[r];
 65     if (p == q) {
 66         reset(p);
 67         for (int i = l; i <= r; ++i) {
 68             sum[p] += (val-1)*a[i]%mod;
 69             a[i] *= val, a[i] %= mod;
 70         }
 71         for (int i = p+1; i <= q-1; ++i) {
 72             mul[i] *= val, mul[i] %= mod;
 73             add[i] *= val, add[i] %= mod;
 74             sum[i] *= val, sum[i] %= mod;
 75         }
 76     }
 77     else {
 78         reset(p);
 79         for (int i = l; i <= R[p]; ++i) {
 80             sum[p] += (val-1)*a[i]%mod;
 81             a[i] *= val, a[i] %= mod;
 82         }
 83         reset(q);
 84         for (int i = L[q]; i <= r; ++i) {
 85             sum[q] += (val-1)*a[i]%mod;
 86             a[i] *= val, a[i] %= mod;
 87         }
 88         for (int i = p+1; i <= q-1; ++i) {
 89             mul[i] *= val, mul[i] %= mod;
 90             add[i] *= val, add[i] %= mod;
 91             sum[i] *= val, sum[i] %= mod;
 92         }
 93     }
 94 }
 95 ll query(int l, int r) {
 96     ll ans = 0;
 97     int p = pos[l], q = pos[r];
 98     if (p == q) {
 99         for (int i = l; i <= r; ++i)
100             ans += (a[i]*mul[p] + add[p])%mod;
101     }
102     else {
103         for (int i = l; i <= R[p]; ++i)
104             ans += (a[i]*mul[p] + add[p])%mod;
105 
106         for (int i = L[q]; i <= r; ++i)
107             ans += (a[i]*mul[q] + add[q])%mod;
108 
109         for (int i = p+1; i <= q-1; ++i)
110             ans += sum[i];
111     }
112     return ans;
113 }
114 int main() {
115     fread(buf,1,70000000,stdin);
116     n = read(n), m = read(m), mod = read(mod);
117     block = sqrt(n);
118     for (rg int i = 1; i <= n; ++i) pos[i] = i/block;
119     for (rg int i = n; i >= 1; --i) L[pos[i]] = i;
120     for (rg int i = 1; i <= n; ++i) R[pos[i]] = i;
121     for (rg int i = 1; i <= n; ++i) a[i] = read(a[i]);
122     for (rg int i = 1; i <= n; ++i) sum[pos[i]] += a[i];
123     for (rg int i = pos[1]; i <= pos[n]; ++i) mul[i] = 1;
124 
125     for (int i = 1; i <= m; ++i) {
126         int op, l, r;
127         op = read(op), l = read(l), r = read(r);
128         if (op == 1) {
129             val = read(val);
130             Mul(l,r,val);
131         }
132         else if (op == 2) {
133             val = read(val);
134             Add(l,r,val);
135         }
136         else {
137             write(query(l,r)%mod);
138             putchar('\n');
139         }
140     }
141 }

 

posted @ 2019-10-23 17:06  麻辣猪仔  阅读(165)  评论(0编辑  收藏  举报