BZOJ 3038 -- 上帝造题的七分钟2 发表于 2019-05-28 | 更新于 2019-06-17 | 分类于 数据结构 , 树状数组 | 评论数: 摘要区间开平方维护区间和 题面解注意到进行少量开平方操作,值就会变为 1 于是暴力开方,把 1 跳过即可 用并查集维护下一个 1 的位置 Code12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182#include <cstdio>#include <cmath>#include <algorithm>using std::swap;const int MAXN=100011;int N, M;int F[MAXN];long long A[MAXN];long long C[MAXN];inline int lowbit(const int &a){ return a&(-a);}inline void Add(const int &p, const long long &d){ for(int i=p;i<=N;i+=lowbit(i)) C[i]+=d;}inline long long Ask(const int &p){ long long ret=0LL; for(int i=p;i>0;i-=lowbit(i)) ret+=C[i]; return ret;}int Find(const int &a){ return a==F[a]?a:F[a]=Find(F[a]);}void Deal(int p){ Add(p, -A[p]); A[p]=sqrt(A[p]); Add(p, A[p]);}void Modi(int l, int r){ for(int i=Find(l);i<=r;++i, i=Find(i)){ Deal(i); if(A[i]==1) F[i]=i+1; }}int main(){ scanf("%d", &N); for(int i=1;i<=N;++i){ scanf("%lld", &A[i]); F[i]=i; } F[N+1]=N+1; for(int i=1;i<=N;++i) Add(i, A[i]); scanf("%d", &M); for(int t, l, r;M--;){ scanf("%d%d%d", &t, &l, &r); if(l>r) swap(l, r); if(t) printf("%lld\n", Ask(r)-Ask(l-1)); else Modi(l, r); } return 0;}/*101 2 3 4 5 6 7 8 9 1050 1 101 1 101 1 50 5 81 4 8*/