Luogu p4145 上帝造題的七分鐘2 題解 線段樹
阿新 • • 發佈:2018-12-13
題目連結 這道題其實和上帝造題的七分鐘1沒有什麼關係,是一道線段樹的題。
筆者是第一次看見區間整體開方的題,開始有點慌,結果發現並不難。通過計算,我們不難得出這道題最大可能有的數1e12只需要經過6次開方就可以變成接近1的數,我們又知道如果一個數等於1,那麼它的開方永遠還是1.
因此,我們又可以發現,這道題的資料只有1e5,是可以支援暴力修改的,只需要看這段區間最大值是否超過1. 所以,我們可以發現這道題就是一道線段樹還不加lazy的暴力修改。但是由於筆者是個蒟蒻,讀入優化寫的是int型別硬是沒查出來,結果交了十幾遍五十分 具體程式碼如下
#include<bits/stdc++.h> using namespace std; int n,m; long long p[100010]; struct node{ int l,r; long long value; }tree[400010]; inline long long read(){ long long s=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar())if(c=='-')f=-1; for(;isdigit(c);c=getchar())s=(s<<3)+(s<<1)+(c^48); return s*f; } inline void write(long long x){ if(x<0){putchar('-');x=-x;} if(x>9) write(x/10); putchar(x%10+'0'); } void build(int l,int r,int number){ if(l==r){ tree[number].value=p[l]; return; } int mid=(l+r)>>1; build(l,mid,number<<1); build(mid+1,r,number<<1|1); tree[number].value=tree[number<<1].value+tree[number<<1|1].value; } void in(int l,int r,int number,int ll,int rr){ if(r-l+1==tree[number].value)return; if(l==r){ tree[number].value=floor(sqrt(tree[number].value)); return; } int mid=(l+r)>>1; if(ll<=mid)in(l,mid,number<<1,ll,rr); if(rr>mid)in(mid+1,r,number<<1|1,ll,rr); tree[number].value=tree[number<<1].value+tree[number<<1|1].value; } long long query(int l,int r,int number,int ll,int rr){ if(ll<=l&&r<=rr){ return tree[number].value; } long long s=0; int mid=(l+r)>>1; if(ll<=mid)s+=query(l,mid,number<<1,ll,rr); if(rr>mid)s+=query(mid+1,r,number<<1|1,ll,rr); return s; } int main(){ n=read(); for(int i=1;i<=n;i++)p[i]=read(); build(1,n,1); m=read(); for(int i=1;i<=m;i++){ int opt=read(),x=read(),y=read(); if(x>y)swap(x,y); if(opt){ long long ans=query(1,n,1,x,y); write(ans);putchar('\n'); } else in(1,n,1,x,y); } return 0; }