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 }
View Code
转载于:https://www.cnblogs.com/Recoder/p/5762299.html
HDU 5828 Rikka with Sequence (线段树+剪枝优化)相关推荐
- HDU 6089 Rikka with Terrorist (线段树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...
- hdu - 6681 Rikka with Cake 线段树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意:给定一个左下顶点为,右上顶点为的矩形,然后给你k条射线,每条射线的起点及方向(上下左右)都 ...
- HDU 1166 敌兵布阵(线段树:点更新,区间求和)
HDU 1166 敌兵布阵(线段树:点更新,区间求和) http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意: 给你n个整数,然后给你多条命令,每条命令如 ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 2019CCPC网络赛 1002 HDU 6703(权值线段树)
2019CCPC网络赛 1002 HDU 6703(权值线段树) 思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中 ...
- HDU 6070 Dirt Ratio(线段树、二分)
http://acm.hdu.edu.cn/showproblem.php?pid=6070 题解 首先不难看出错误率是单调的,那么我们可以直接二分答案x,某个区间的错误率=区间数的种类cnt/区间长 ...
- hdu 5692 Snacks(dfs序+线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692 解题思路:这道题是树节点的点权更新,而且涉及到子树,常用的思路是利用dfs序,用线段树来对区间进 ...
- Minimum Inversion Number HDU - 1394(权值线段树/树状数组)
The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that s ...
- hdu 4391 Paint The Wall 线段树 +优化 2012 Multi-University Training Contest 10 )
http://acm.hdu.edu.cn/showproblem.php?pid=4391 题意: 刷墙, 以开始 有 n个节点,每个节点有一种颜色 ,m 次询问 m次 输入 a,l,r,z 如果 ...
最新文章
- java restful接口开发实例_Spring Boot 中 10 行代码构建 RESTful 风格应用!
- 手把手教你搭建 ELK 实时日志分析平台
- POJ 2253 Frogger(最短路Floyd)题解
- 20本最好的Linux免费书籍
- atitit。wondows 右键菜单的管理与位置存储
- 22 WM配置-策略-入库策略2-定义未清存储策略C(Open Strategy)
- .net操作xml小结 (转)
- 深度测试与alpha混合(1)
- leetcode 14 最长公共前缀(python)
- 在linux中配置编译u-boot方法,U-Boot编译过程解析
- 曙光服务器bios开启vt虚拟化,BIOS怎么开启虚拟化技术VT
- Skype国际版最新版及老版本下载
- mysql中key的用法_数据库中KEY的用法
- Golang 逃逸分析
- 实现现代汽车SoC功能安全的实践和挑战
- 【BlockingQueue】BlockingQueue接口方法说明和区别
- java.lang.NoClassDefFoundError异常解决
- 2020年 java题库
- HBuilderX 最新安装使用教程,附详细图解,持续更新
- 02笔记 离散数学——命题逻辑——基于离散数学(第3版)_章炯民,陶增乐