[HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)
2016-05-16 10:27
555 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027
RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和。昨晚思前想后找有没有一个数学上的开平方的和等于和的开平方之类的规律。但是想了想发现这不就是小的时候,如果你这么想那老师就会骂死你的那个- -!
所以显然这个题是无法按套路成段更新了,懒惰标记也是没有用了,我们应该去按照区间更新每一个节点。结果TLE了一发,这说明这题不是这么搞,一定还有规律的。注意到题目给数据规模是2^63以及题目红字所述:开根号全都取下整,除了考虑用longlong以外,我们其实还可以想一下对一个longlong的数据开平方,最终都会变成1。那么在更新这个节点至1的那次update里,更新结束后一定会从叶子rt向上更新父亲,如果rt的兄弟节点也是1,那么说明rt的父亲已经不再需要更新了(因为1开平方还是1),这时候rt的父亲存的结果是1+1=2。也就是(rt+1-rt+1)。推广到更高的节点,换成区间来表示就是(r-l+1)。我们遇到这种节点就不需要更新了。
特别需要注意的是题目中x和y的大小…会出现x>y的情况……以及,每个case最后都要有一个额外的\n…………(PE到死WA到死)
RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和。昨晚思前想后找有没有一个数学上的开平方的和等于和的开平方之类的规律。但是想了想发现这不就是小的时候,如果你这么想那老师就会骂死你的那个- -!
所以显然这个题是无法按套路成段更新了,懒惰标记也是没有用了,我们应该去按照区间更新每一个节点。结果TLE了一发,这说明这题不是这么搞,一定还有规律的。注意到题目给数据规模是2^63以及题目红字所述:开根号全都取下整,除了考虑用longlong以外,我们其实还可以想一下对一个longlong的数据开平方,最终都会变成1。那么在更新这个节点至1的那次update里,更新结束后一定会从叶子rt向上更新父亲,如果rt的兄弟节点也是1,那么说明rt的父亲已经不再需要更新了(因为1开平方还是1),这时候rt的父亲存的结果是1+1=2。也就是(rt+1-rt+1)。推广到更高的节点,换成区间来表示就是(r-l+1)。我们遇到这种节点就不需要更新了。
特别需要注意的是题目中x和y的大小…会出现x>y的情况……以及,每个case最后都要有一个额外的\n…………(PE到死WA到死)
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; #define fr first #define sc second #define pb(a) push_back(a) #define Rint(a) scanf("%d", &a) #define Rll(a) scanf("%I64d", &a) #define Rs(a) scanf("%s", a) #define FRead() freopen("in", "r", stdin) #define FWrite() freopen("out", "w", stdout) #define Rep(i, len) for(LL i = 0; i < (len); i++) #define For(i, a, len) for(LL i = (a); i < (len); i++) #define Cls(a) memset((a), 0, sizeof(a)) #define Full(a) memset((a), 0x7f7f, sizeof(a)) typedef long long LL; #define lrt rt << 1 #define rrt rt << 1 | 1 const LL maxn = 100100; LL sum[maxn<<2]; LL n, q; void pushUP(LL rt) { sum[rt] = sum[lrt] + sum[rrt]; } void build(LL l, LL r, LL rt) { if(l == r) { Rll(sum[rt]); return; } LL m = (l + r) >> 1; build(l, m, lrt); build(m+1, r, rrt); pushUP(rt); } void update(LL L, LL R, LL l, LL r, LL rt) { if(sum[rt] == r - l + 1) return; if(l == r) { sum[rt] = LL(double(sqrt(sum[rt]))); return; } LL m = (l + r) >> 1; if(m >= L) update(L, R, l, m, lrt); if(m < R) update(L,R, m+1, r, rrt); pushUP(rt); } LL query(LL L, LL R, LL l, LL r, LL rt) { if(l >= L && R >= r) return sum[rt]; LL m = (l + r) >> 1; LL ret = 0; if(m >= L) ret += query(L, R, l, m, lrt); if(m < R) ret += query(L, R, m+1, r, rrt); return ret; } int main() { // FRead(); LL orz = 1; LL a, b, c; while(~Rll(n)) { Cls(sum); printf("Case #%I64d:\n", orz++); build(1, n, 1); Rll(q); while(q--) { Rll(a); Rll(b); Rll(c); if(b > c) swap(b, c); if(a == 0) update(b, c, 1, n, 1); if(a == 1) cout << query(b, c, 1, n, 1) << endl; } printf("\n"); } return 0; }
相关文章推荐
- MySQL中因为unique key 非空唯一索引存在导致修改主键失败案例
- 347. Top K Frequent Elements
- 解决tableView separate 分割线不从最左边开始问题
- hibernate提供了强大的查询系统,query.setFirstResult,query.setMaxResults
- uva 11572 unique snowflakes——yhx
- uva 1152 4 values whose sum is zero ——yhx
- uva 1605 building for UN ——yhx
- 通过Service Builder改变了原数据库的主键,所有原有记录被删除。
- NUI四种提交数据方式c
- Hibernate动态条件查询(Criteria Query)
- HZAU 21——Arithmetic Sequence——————【暴力 or dp】
- this android sdk requires a...adt
- android:layout_centerInParent = "true"和 android:layout_gravity = "center"
- Android中UI的单位dp,sp和px使用问题
- 通过添加uiTOOLBAR制作毛玻璃效果
- 自定义UICollectionViewLayout(能滚动)需要实现的方法
- 重写UICollectoinViewFlowLayout需要重写的方法
- LeetCode 52. N-Queens II
- 定义一个UIEdgeInset全局变量
- 根据segue跳转