WuliWuliiii
凤兮凤兮归故乡 遨游四海求其凰

模板题链接

可以从HDU-5306开始练手。

吉司机线段树可以解决什么问题?

譬如说区间操作:对[L, R]区间,使得L ≤ i ≤ R,a[i] = min(a[i], x)。

然后还有区间求和、求max、min这样的操作。

我们可以用O((n + q)log(n))的复杂度来解决这个问题。

只需要存储这样的几个值:

  1. mx[rt]表示以rt为根的区间的最大值
  2. md[rt]表示以rt为根的区间的严格次大值
  3. cnt[rt]表示以rt为根的区间的最大值的个数
  4. sum[rt]表示以rt为根的区间和的值
  5. lazy[rt]表示以rt为根的区间,现在的懒标记(记录更新的值,但是不下推)

然后我们可以以这五个数组来用以维护一个吉司机线段树。

 

操作:

如果mx[rt] ≤ x,那么x就是无效的更改,没用,return;

如果md[rt] ≥ x,我们需要对于左右子树区间进行暴力更改;

剩下的情况就是md[rt] < x < mx[rt],那么此时只需要更改目前子树的mx[rt]值就可以了,当然,我们在这里需要打lazy懒标记,因为我们不下传这个值了。

 

时间复杂度的证明的关键点,就是在于对于区间的种类数的改变,因为只有暴力更改的时候才会造成高复杂度,但是会发现每次暴力更改,只会让区间的数的种类数减少,而减少的次数肯定是有限的,所以复杂度实际上不是很高。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <string>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <limits>
  8 #include <vector>
  9 #include <stack>
 10 #include <queue>
 11 #include <set>
 12 #include <map>
 13 #include <bitset>
 14 #include <unordered_map>
 15 #include <unordered_set>
 16 #define lowbit(x) ( x&(-x) )
 17 #define pi 3.141592653589793
 18 #define e 2.718281828459045
 19 #define INF 0x3f3f3f3f
 20 #define HalF (l + r)>>1
 21 #define lsn rt<<1
 22 #define rsn rt<<1|1
 23 #define Lson lsn, l, mid
 24 #define Rson rsn, mid+1, r
 25 #define QL Lson, ql, qr
 26 #define QR Rson, ql, qr
 27 #define myself rt, l, r
 28 #define pii pair<int, int>
 29 #define MP(a, b) make_pair(a, b)
 30 using namespace std;
 31 typedef unsigned long long ull;
 32 typedef unsigned int uit;
 33 typedef long long ll;
 34 const int maxN = 1e6 + 7;
 35 int N, M;
 36 int mx[maxN << 2], md[maxN << 2], cnt[maxN << 2], lazy[maxN << 2];
 37 ll sum[maxN << 2];
 38 void pushup(int rt)
 39 {
 40     sum[rt] = sum[lsn] + sum[rsn];
 41     if(mx[lsn] == mx[rsn])
 42     {
 43         mx[rt] = mx[lsn];
 44         cnt[rt] = cnt[lsn] + cnt[rsn];
 45         md[rt] = max(md[lsn], md[rsn]);
 46     }
 47     else if(mx[lsn] > mx[rsn])
 48     {
 49         mx[rt] = mx[lsn];
 50         cnt[rt] = cnt[lsn];
 51         md[rt] = max(mx[rsn], md[lsn]);
 52     }
 53     else
 54     {
 55         mx[rt] = mx[rsn];
 56         cnt[rt] = cnt[rsn];
 57         md[rt] = max(mx[lsn], md[rsn]);
 58     }
 59 }
 60 void build(int rt, int l, int r)
 61 {
 62     lazy[rt] = -1;
 63     if(l == r) { scanf("%d", &mx[rt]); md[rt] = -1; cnt[rt] = 1; sum[rt] = mx[rt]; return; }
 64     int mid = HalF;
 65     build(Lson);
 66     build(Rson);
 67     pushup(rt);
 68 }
 69 void pushdown(int rt)
 70 {
 71     if(~lazy[rt])
 72     {
 73         if(lazy[rt] < mx[lsn])
 74         {
 75             sum[lsn] = sum[lsn] - 1LL * cnt[lsn] * (mx[lsn] - lazy[rt]);
 76             mx[lsn] = lazy[rt];
 77             lazy[lsn] = lazy[rt];
 78         }
 79         if(lazy[rt] < mx[rsn])
 80         {
 81             sum[rsn] = sum[rsn] - 1LL * cnt[rsn] * (mx[rsn] - lazy[rt]);
 82             mx[rsn] = lazy[rt];
 83             lazy[rsn] = lazy[rt];
 84         }
 85         lazy[rt] = -1;
 86     }
 87 }
 88 void update(int rt, int l, int r, int ql, int qr, int val)
 89 {
 90     if(r < ql || l > qr || val >= mx[rt]) return;
 91     pushdown(rt);
 92     int mid = HalF;
 93     if(md[rt] >= val)
 94     {
 95         update(QL, val);
 96         update(QR, val);
 97         pushup(rt);
 98     }
 99     else
100     {
101         if(ql <= l && qr >= r)
102         {
103             lazy[rt] = val;
104             sum[rt] = sum[rt] - 1LL * cnt[rt] * (mx[rt] - val);
105             mx[rt] = val;
106         }
107         else
108         {
109             pushdown(rt);
110             if(qr <= mid) update(QL, val);
111             else if(ql > mid) update(QR, val);
112             else { update(QL, val); update(QR, val); }
113             pushup(rt);
114         }
115     }
116 }
117 int query_max(int rt, int l, int r, int ql, int qr)
118 {
119     if(ql <= l && qr >= r) return mx[rt];
120     pushdown(rt);
121     int mid = HalF;
122     if(qr <= mid) return query_max(QL);
123     else if(ql > mid) return query_max(QR);
124     else return max(query_max(QL), query_max(QR));
125 }
126 ll query_sum(int rt, int l, int r, int ql, int qr)
127 {
128     if(ql <= l && qr >= r) return sum[rt];
129     pushdown(rt);
130     int mid = HalF;
131     if(qr <= mid) return query_sum(QL);
132     else if(ql > mid) return query_sum(QR);
133     else return query_sum(QL) + query_sum(QR);
134 }
135 int main()
136 {
137     int T; scanf("%d", &T);
138     while(T --)
139     {
140         scanf("%d%d", &N, &M);
141         build(1, 1, N);
142         for(int i=1, op, l, r, x; i<=M; i++)
143         {
144             scanf("%d%d%d", &op, &l, &r);
145             switch (op)
146             {
147                 case 0:
148                 {
149                     scanf("%d", &x);
150                     update(1, 1, N, l, r, x);
151                     break;
152                 }
153                 case 1:
154                 {
155                     printf("%d\n", query_max(1, 1, N, l, r));
156                     break;
157                 }
158                 default:
159                 {
160                     printf("%lld\n", query_sum(1, 1, N, l, r));
161                     break;
162                 }
163             }
164         }
165     }
166     return 0;
167 }
168 /*
169 1
170 5 2
171 4 3 3 2 2
172 0 2 3 2
173 1 2 5
174 ans:2
175 */

 

posted on 2020-09-21 15:08  唔哩Wulili  阅读(248)  评论(0编辑  收藏  举报