P4145 上帝造題的七分鐘 2 / 花神遊歷各國(線段樹)
阿新 • • 發佈:2021-07-21
區間開平方直接上暴力即可。
因為一個數開幾次就到1了。
維護一個區間最大值,當該區間最大值是1的時候直接return。
複雜度O(nlognlogn)?
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; int n,m; long long a[maxn],c[maxn<<2],mx[maxn<<2]; void build (int i,int l,int r) { if (l==r) { c[i]=mx[i]=a[l]; return; } int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); c[i]=c[i<<1]+c[i<<1|1]; mx[i]=max(mx[i<<1],mx[i<<1|1]); } void up (int i,int l,int r,int L,int R) { if (mx[i]==1) return; if (l==r) { c[i]=sqrt(c[i]); mx[i]=sqrt(mx[i]); return; } int mid=(l+r)>>1; if (L<=mid) up(i<<1,l,mid,L,R); if (R>mid) up(i<<1|1,mid+1,r,L,R); c[i]=c[i<<1]+c[i<<1|1]; mx[i]=max(mx[i<<1],mx[i<<1|1]); } long long query (int i,int l,int r,int L,int R) { if (l>=L&&r<=R) return c[i]; int mid=(l+r)>>1; long long ans=0; if (L<=mid) ans+=query(i<<1,l,mid,L,R); if (R>mid) ans+=query(i<<1|1,mid+1,r,L,R); return ans; } int main () { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld",a+i); build(1,1,n); int q; scanf("%d",&q); while (q--) { int k,l,r; scanf("%d%d%d",&k,&l,&r); if (l>r) swap(l,r); if (k==0) { up(1,1,n,l,r); } else { printf("%lld\n",query(1,1,n,l,r)); } } }