BZOJ 3038 上帝造题的七分钟2 树状数组+并查集
题目大意:一个序列,有两种操作。1.将一段数中的每个数开根号。2.查询一段数的和。
思路:和3211是一个题,有兴趣的能够看看我的那篇博客。
CODE:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 100010 using namespace std; int cnt,asks; long long src[MAX]; long long fenwick[MAX]; int father[MAX]; void Pretreatment(); inline void Fix(int x,long long c); inline long long GetSum(int x); int Find(int x); int main() { cin >> cnt; Pretreatment(); for(int i = 1;i <= cnt; ++i) { scanf("%lld",&src[i]); Fix(i,src[i]); if(src[i] == 1) father[i] = i + 1; } cin >> asks; for(int flag,x,y,i = 1;i <= asks; ++i) { scanf("%d%d%d",&flag,&x,&y); if(x > y) swap(x,y); if(!flag) for(x = Find(x);x <= y;x = Find(x + 1)) { Fix(x,-src[x]); Fix(x,src[x] = sqrt(src[x])); if(src[x] == 1) father[x] = Find(x + 1); } else printf("%lld\n",GetSum(y) - GetSum(x - 1)); } return 0; } void Pretreatment() { for(int i = 1;i <= cnt + 1; ++i) father[i] = i; } inline void Fix(int x,long long c) { for(int i = x;i <= cnt;i += i&-i) fenwick[i] += c; } inline long long GetSum(int x) { long long re = 0; for(int i = x;i;i -= i&-i) re += fenwick[i]; return re; } int Find(int x) { if(father[x] == x) return x; return father[x] = Find(father[x]); }
posted on 2017-06-13 14:53 yjbjingcha 阅读(211) 评论(0) 编辑 收藏 举报