最大的数开根号最多7次到1,每次单点更新,对于全是1的区间标记不用再更新。
注意l>r的情况
#include<cstring> #include<string> #include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<map> #include<cstdlib> #include<cmath> #include<vector> //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 600004 int n; __int64 sum[maxn]; int tag[maxn]; void pushup(int k) { sum[k]=sum[k<<1]+sum[k<<1|1]; if(tag[k<<1]&&tag[k<<1|1]) tag[k]=1; else tag[k]=0; } void init(int l,int r,int k) { sum[k]=0; tag[k]=0; if(l==r) { scanf("%I64d",&sum[k]); if(sum[k]==1) tag[k]=1; return ; } int mid=(l+r)>>1; init(l,mid,2*k); init(mid+1,r,2*k+1); pushup(k); } void update(int l,int r,int s,int e,int k) { if(tag[k]) return ; if(s==l&&e==r&&l==r) { __int64 temp=(__int64)sqrt(sum[k]*1.0); // __int64 i=(temp-10>=0)?temp-10:0; // for(;i*i<=sum[k];i++); sum[k]=temp; if(sum[k]==1) tag[k]=1; return ; } int mid=(s+e)>>1; if(r<=mid) update(l,r,s,mid,k<<1); else if(l>mid) update(l,r,mid+1,e,k<<1|1); else { update(l,mid,s,mid,k<<1); update(mid+1,r,mid+1,e,k<<1|1); } pushup(k); } __int64 query(int l,int r,int s,int e,int k) { if(tag[k]) return r-l+1; if(s==l&&r==e) { return sum[k]; } int mid=(s+e)>>1; if(r<=mid) return query(l,r,s,mid,k<<1); else if(l>mid) return query(l,r,mid+1,e,k<<1|1); else return query(l,mid,s,mid,k<<1)+query(mid+1,r,mid+1,e,k<<1|1); } int main() { int ca=1; while(scanf("%d",&n)!=EOF) { printf("Case #%d:\n",ca++); init(1,n,1); int q; scanf("%d",&q); while(q--) { int c; scanf("%d",&c); if(c==1) { int a,b; scanf("%d%d",&a,&b); if(a>b) swap(a,b); __int64 ans=query(a,b,1,n,1); printf("%I64d\n",ans); } else { int a,b; scanf("%d%d",&a,&b); if(a>b) swap(a,b); update(a,b,1,n,1); } } printf("\n"); } return 0; }