码迷,mamicode.com
首页 > 其他好文 > 详细

线段树中区间加减和区间覆盖的双标记问题

时间:2018-10-31 01:04:30      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:can   lazy   space   def   ons   问题   线段   c++   sum   

HDU 5828

吉老师真厉害。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define lson q << 1
  4 #define rson (q << 1) | 1
  5 #define mid ((l + r) >> 1)
  6 typedef long long ll;
  7 const int maxn = 1e5 + 50;
  8 ll maxv[maxn << 2];
  9 ll minv[maxn << 2];
 10 ll sum[maxn << 2];
 11 ll lazy[maxn << 2];
 12 ll cover[maxn << 2];
 13 int segl[maxn << 2], segr[maxn << 2];
 14 int a[maxn];
 15 void push_up(int q)
 16 {
 17     maxv[q] = max(maxv[lson], maxv[rson]);
 18     minv[q] = min(minv[lson], minv[rson]);
 19     sum[q] = sum[lson] + sum[rson];
 20 }
 21 void build(int q, int l, int r)
 22 {
 23     lazy[q] = cover[q] = 0;
 24     segl[q] = l, segr[q] = r;
 25     maxv[q] = minv[q] = sum[q] = 0;
 26     if(l == r)
 27     {
 28         sum[q] = maxv[q] = minv[q] = a[l];
 29         return;
 30     }
 31     build(lson, l, mid);
 32     build(rson, mid + 1, r);
 33     push_up(q);
 34 }
 35 void push_down(int q)
 36 {
 37     if(cover[q])
 38     {
 39         maxv[lson] = minv[lson] = cover[q] + lazy[q];
 40         cover[lson] = minv[lson];
 41         sum[lson] = (ll)(segr[lson] - segl[lson] + 1) * minv[lson];
 42         maxv[rson] = minv[rson] = cover[q] + lazy[q];
 43         cover[rson] = minv[rson];
 44         sum[rson] = (ll)(segr[rson] - segl[rson] + 1) * minv[rson];
 45         lazy[q] = cover[q] = lazy[lson] = lazy[rson] = 0;
 46     }
 47     else if(lazy[q])
 48     {
 49         lazy[lson] += lazy[q];
 50         minv[lson] += lazy[q];
 51         maxv[lson] += lazy[q];
 52         sum[lson] += (ll)(segr[lson] - segl[lson] + 1) * lazy[q];
 53         lazy[rson] += lazy[q];
 54         minv[rson] += lazy[q];
 55         maxv[rson] += lazy[q];
 56         sum[rson] += (ll)(segr[rson] - segl[rson] + 1) * lazy[q];
 57         lazy[q] = 0;
 58     }
 59 }
 60 void change(int q, int l, int r, int ql, int qr, int x)
 61 {
 62     if(qr < l || ql > r) return;
 63     if(ql <= l && qr >= r)
 64     {
 65         lazy[q] += x;
 66         maxv[q] += x;
 67         minv[q] += x;
 68         sum[q] += (ll)(r - l + 1) * x;
 69         return;
 70     }
 71     push_down(q);
 72     change(lson, l, mid, ql, qr, x);
 73     change(rson, mid + 1, r, ql, qr, x);
 74     push_up(q);
 75 }
 76 void change(int q, int l, int r, int ql, int qr)
 77 {
 78     if(qr < l || ql > r) return;
 79     if(ql <= l && qr >= r && maxv[q] - minv[q] <= 1LL)
 80     {
 81         if(maxv[q] == minv[q] || (ll)sqrt(maxv[q]) == (ll)sqrt(minv[q]))
 82         {
 83             maxv[q] = minv[q] = sqrt(minv[q]);
 84             cover[q] = maxv[q];
 85             lazy[q] = 0;
 86             sum[q] = (ll)(r - l + 1) * maxv[q];
 87         }
 88         else
 89         {
 90             lazy[q] += -1LL * (minv[q] - (ll)sqrt(minv[q]));
 91             sum[q] -= (ll)(r - l + 1) * (minv[q] - (ll)sqrt(minv[q]));
 92             minv[q] = sqrt(minv[q]);
 93             maxv[q] = minv[q] + 1;
 94         }
 95         return;
 96     }
 97     push_down(q);
 98     change(lson, l, mid, ql, qr);
 99     change(rson, mid + 1, r, ql, qr);
100     push_up(q);
101 }
102 ll query(int q, int l, int r, int ql, int qr)
103 {
104     if(qr < l || ql > r) return 0;
105     if(ql <= l && qr >= r)
106     {
107         return sum[q];
108     }
109     push_down(q);
110     ll ret = 0;
111     ret += query(lson, l, mid, ql, qr);
112     ret += query(rson, mid + 1, r, ql, qr);
113     return ret;
114 }
115 int main()
116 {
117     int T; scanf("%d", &T);
118     while(T--)
119     {
120         int n, m; scanf("%d %d", &n, &m);
121         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
122         build(1, 1, n);
123         for(int i = 1; i <= m; i++)
124         {
125             int type, l, r, x;
126             scanf("%d", &type);
127             if(type == 1)
128             {
129                 scanf("%d %d %d", &l, &r, &x);
130                 change(1, 1, n, l, r, x);
131             }
132             else if(type == 2)
133             {
134                 scanf("%d %d", &l, &r);
135                 change(1, 1, n, l, r);
136             }
137             else if(type == 3)
138             {
139                 scanf("%d %d", &l, &r);
140                 printf("%lld\n", query(1, 1, n, l, r));
141             }
142         }
143     }
144     return 0;
145 }

 

线段树中区间加减和区间覆盖的双标记问题

标签:can   lazy   space   def   ons   问题   线段   c++   sum   

原文地址:https://www.cnblogs.com/wangwangyu/p/9880271.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!