刚开始的时候第一反应这道题是成段的更新,不能一个数一个数的更新,那样肯定会超时的!
但是再想了一会儿之后,发现成段更新比较困难,主要是这道题的每个节点的更新并不是统一的(也就是说并不是都加K,或者都减K之类的);
所以我们并不能像一般的成段更新那样去更新。
再仔细观察后,其实我们可以很容易的发现,一个数k(k<=2^63-1)在经过最多6,7次的开平方根后,必然会变成1,而且当1的平方根也是1;
也就是说当一个数为1的时候,我们没有必要对它进行操作和更新;而且一个很大的数仅仅经过6,7次就可以变成1;
所以到这里我们因该就可以形成一个解题的大体思路了:
每当我们要进行更新操作的时候,我们先判断一下这个区间是否有必要进行更新(若全都是1就没有更新的必要了);
判断的方法很简单:就是看该区间的长度和该区间内的总值是否相等;
当我们确认有必要进行更新的时候,我们就要多整个区间进行更新,当然在进行更新的时候,要不断的保存T[root].sum值;
接下来的就是很水很水的区间求和了!!
#include <queue> #include <stack> #include <cmath> #include <cstdio> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string> #include <cstring> #include <algorithm> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <algorithm> #define LL __int64 using namespace std; const int N=100010; struct Node { int L,R; LL len; LL sum; } t[N*4]; LL data[N]; int n,q; void up(int fa){ t[fa].sum=t[fa<<1].sum+t[fa<<1|1].sum; } void down(int l,int r,int fa) { if(t[fa].L==t[fa].R) { t[fa].sum=(LL)(sqrt(t[fa].sum)); return; } int ls=fa<<1; int rs=fa<<1|1; int mid=(t[fa].L+t[fa].R)/2; down(l,mid,ls); down(mid+1,r,rs); up(fa); } void built(int l,int r,int fa) { t[fa].L=l; t[fa].R=r; t[fa].len=r-l+1; t[fa].sum=0LL; if(l==r) { t[fa].sum=data[l]; return; } int mid=(l+r)/2; built(l,mid,fa<<1); built(mid+1,r,fa<<1|1); up(fa); } void update(int l,int r,int fa) { int ls=fa<<1; int rs=fa<<1|1; int mid=(t[fa].L+t[fa].R)/2; if(t[fa].L==l&&t[fa].R==r) { if(t[fa].sum==t[fa].len) return ; down(l,r,fa); return ; } if(r<=mid) update(l,r,ls); else if(l>mid) update(l,r,rs); else { update(l,mid,ls); update(mid+1,r,rs); } up(fa); } LL query(int l,int r,int fa) { int ls=fa<<1; int rs=fa<<1|1; int mid=(t[fa].L+t[fa].R)/2; if(t[fa].L>=l&&t[fa].R<=r) return t[fa].sum; if(r<=mid) return query(l,r,ls); else if(l>mid) return query(l,r,rs); else return query(l,mid,ls)+query(mid+1,r,rs); } int main() { int t=1; while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; i++) scanf("%I64d",&data[i]); built(1,n,1); int a,b,c; printf("Case #%d:\n",t++); cin>>q; while(q--) { scanf("%d%d%d",&a,&b,&c); if(b>c)swap(b,c); if(a) cout<<query(b,c,1)<<endl; else update(b,c,1); } cout<<endl; } return 0; }