P4145 上帝造题的七分钟2 / 花神游历各国(线段树区间开平方)
有点意思,不需要什么懒标记之类的东西,因为一个数无论怎样开平方,最后取整的结果必然会是1,所以我们不妨用最大值来维护,若区间最大值不为1,就暴力修改,否则不用管。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; struct node { int l; int r; unsigned long long sum; unsigned long long mx; }tree[maxn*4]; int n,m; unsigned long long l,r,opt; unsigned long long a[maxn]; void build(int now,int l,int r) { tree[now].l=l; tree[now].r=r; if(l==r) { tree[now].sum=tree[now].mx=a[l]; return; } int mid=(l+r)>>1; build(now*2,l,mid); build(now*2+1,mid+1,r); tree[now].sum=tree[now*2].sum+tree[now*2+1].sum; tree[now].mx=max(tree[now*2].mx,tree[now*2+1].mx); } void update(int now,int l,int r) { if(tree[now].l==tree[now].r) { tree[now].sum=sqrt(tree[now].sum); tree[now].mx=sqrt(tree[now].mx); return; } int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid&&tree[now*2].mx>1) { update(now*2,l,r); } if(r>mid&&tree[now*2+1].mx>1) { update(now*2+1,l,r); } tree[now].sum=tree[now*2].sum+tree[now*2+1].sum; tree[now].mx=max(tree[now*2].mx,tree[now*2+1].mx); } long long query(int now,int l,int r) { if(tree[now].l>=l&&tree[now].r<=r) { return tree[now].sum; } int mid=(tree[now].l+tree[now].r)>>1; long long ans=0; if(l<=mid) { ans+=query(now*2,l,r); } if(mid<r) { ans+=query(now*2+1,l,r); } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&opt,&l,&r); if(l>r) { swap(l,r); } if(opt==0) { update(1,l,r); } else { printf("%lld\n",query(1,l,r)); } } return 0; }
多说几句,数据比较毒瘤,狂开unsigned long long 就能AC