HDU 5828 Rikka with Sequence (线段树+剪枝优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828

给你n个数,三种操作。操作1是将l到r之间的数都加上x;操作2是将l到r之间的数都开方;操作3是求出l到r之间的和。

操作1和3就不说了,关键是开方操作。

一个一个开方,复杂度太高,无疑会T。所以我们来剪枝一下。

我们可以观察,这里一个数最多开方4,5次(loglogx次)就会到1,所以要是一段区间最大值为1的话,就不需要递归开方下去了。这是一个剪枝。

如果一段区间的数都是一样大小(最大值等于最小值),那么开方的话,值也会相同。所以只要一次开方就好了,而一次开方也相当于减去 x-sqrt(x)。这是剪枝二。

有了两个剪枝,原本是过了... 后来数据加强了,就T了,无奈...

  1 //#pragma comment(linker, "/STACK:102400000, 102400000")
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <ctime>
 10 #include <list>
 11 #include <set>
 12 #include <map>
 13 using namespace std;
 14 typedef long long LL;
 15 const int N = 1e5 + 5;
 16 struct SegTree {
 17     int l, r, mid;
 18     LL sum, lazy, Max, Min;
 19 }T[N << 2];
 20 
 21 void build(int p, int l, int r) {
 22     int ls = p << 1, rs = (p << 1)|1;
 23     T[p].l = l, T[p].r = r, T[p].mid = (l + r) >> 1, T[p].lazy = 0;
 24     if(l == r) {
 25         scanf("%lld", &T[p].sum);
 26         T[p].Max = T[p].Min = T[p].sum;
 27         return ;
 28     }
 29     build(ls, l, T[p].mid);
 30     build(rs, T[p].mid + 1, r);
 31     T[p].sum = (T[ls].sum + T[rs].sum);
 32     T[p].Min = min(T[ls].Min, T[rs].Min);
 33     T[p].Max = max(T[ls].Max, T[rs].Max);
 34 }
 35 
 36 void update_add(int p, int l, int r, LL val) {
 37     int ls = p << 1, rs = (p << 1)|1;
 38     if(T[p].l == l && T[p].r == r) {
 39         T[p].Min += val;
 40         T[p].Max += val;
 41         T[p].sum += (r - l + 1) * val;
 42         T[p].lazy += val;
 43         return ;
 44     }
 45     if(T[p].lazy) {
 46         T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
 47         T[ls].sum += (T[ls].r - T[ls].l + 1)*T[p].lazy;
 48         T[rs].sum += (T[rs].r - T[rs].l + 1)*T[p].lazy;
 49         T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
 50         T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
 51         T[p].lazy = 0;
 52     }
 53     if(r <= T[p].mid) {
 54         update_add(ls, l, r, val);
 55     }
 56     else if(l > T[p].mid) {
 57         update_add(rs, l, r, val);
 58     }
 59     else {
 60         update_add(ls, l, T[p].mid, val);
 61         update_add(rs, T[p].mid + 1, r, val);
 62     }
 63     T[p].sum = (T[ls].sum + T[rs].sum);
 64     T[p].Min = min(T[ls].Min, T[rs].Min);
 65     T[p].Max = max(T[ls].Max, T[rs].Max);
 66 }
 67 
 68 void update(int p, int l, int r) {
 69     if(T[p].Max == 1) //最大值为1 就不需要开方了
 70         return ;
 71     int ls = p << 1, rs = (p << 1)|1;
 72     if(T[p].l == l && T[p].r == r && T[p].Max == T[p].Min) {
 73         LL temp = T[p].Max - (LL)sqrt(T[p].Max*1.0);
 74         T[p].Max -= temp;
 75         T[p].Min -= temp;
 76         T[p].lazy -= temp;
 77         T[p].sum -= (r - l + 1)*temp;
 78         return ;
 79     }
 80     if(T[p].lazy) {
 81         T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
 82         T[ls].sum += (T[ls].r - T[ls].l + 1)*T[p].lazy;
 83         T[rs].sum += (T[rs].r - T[rs].l + 1)*T[p].lazy;
 84         T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
 85         T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
 86         T[p].lazy = 0;
 87     }
 88     if(r <= T[p].mid) {
 89         update(ls, l, r);
 90     }
 91     else if(l > T[p].mid) {
 92         update(rs, l, r);
 93     }
 94     else {
 95         update(ls, l, T[p].mid);
 96         update(rs, T[p].mid + 1, r);
 97     }
 98     T[p].sum = (T[ls].sum + T[rs].sum);
 99     T[p].Min = min(T[ls].Min, T[rs].Min);
100     T[p].Max = max(T[ls].Max, T[rs].Max);
101 }
102 
103 LL query(int p, int l, int r) {
104     int ls = p << 1, rs = (p << 1)|1;
105     if(T[p].l == l && T[p].r == r) {
106         return T[p].sum;
107     }
108     if(T[p].lazy) {
109         T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
110         T[ls].sum += (T[ls].r - T[ls].l + 1)*T[p].lazy;
111         T[rs].sum += (T[rs].r - T[rs].l + 1)*T[p].lazy;
112         T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
113         T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
114         T[p].lazy = 0;
115     }
116     if(r <= T[p].mid) {
117         return query(ls, l, r);
118     }
119     else if(l > T[p].mid) {
120         return query(rs, l, r);
121     }
122     else {
123         return query(ls, l, T[p].mid) + query(rs, T[p].mid + 1, r);
124     }
125 }
126 
127 int main()
128 {
129     int n, m, t, c, l, r;
130     LL val;
131     scanf("%d", &t);
132     while(t--) {
133         scanf("%d %d", &n, &m);
134         build(1, 1, n);
135         while(m--) {
136             scanf("%d %d %d", &c, &l, &r);
137             if(c == 1) {
138                 scanf("%lld", &val);
139                 update_add(1, l, r, val);
140             }
141             else if(c == 2) {
142                 update(1, l, r);
143             }
144             else {
145                 printf("%lld
", query(1, l, r));
146             }
147         }
148     }
149     return 0;
150 }
View Code
原文地址:https://www.cnblogs.com/Recoder/p/5762299.html