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\n", query(1, l, r)); 146 } 147 } 148 } 149 return 0; 150 }