HDU 4027 Can you answer these queries? (線段樹+暴力)
阿新 • • 發佈:2018-11-03
題意:
給出一段序列和兩種操作,第一種操作,將x,y區間的數均開平方,第二種操作,對x,y區間進行求和。
分析:
一開始還不敢用線段樹做,因為純線段樹下來根暴力列舉複雜度差不了多少,但由於開方,所以在很少次的迴圈裡就能達到1,所以就可以直接這麼做了。但題目沒有說名忍耐值的範圍,要是0太多這個方法也不好使。
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; typedef long long ll; ll tree[maxn<<2]; void build(int l,int r,int i){ if(l==r){ scanf("%lld",&tree[i]); return; } int mid=l+r>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); tree[i]=tree[i<<1]+tree[i<<1|1]; } void change(int tl,int tr,int l,int r,int i){ if(tl>r||tr<l) return ; if(tl<=l&&r<=tr&&tree[i]<=r-l+1) return; //這部很關鍵。 if(l==r){ tree[i]=sqrt(1.0*tree[i]); return; } int mid=l+r>>1; change(tl,tr,l,mid,i<<1); change(tl,tr,mid+1,r,i<<1|1); tree[i]=tree[i<<1]+tree[i<<1|1]; } ll query(int tl,int tr,int l,int r,int i){ if(tl>r||tr<l) return 0; if(tl<=l&&r<=tr) return tree[i]; int mid=l+r>>1; return query(tl,tr,l,mid,i<<1)+query(tl,tr,mid+1,r,i<<1|1); } int main(){ int n,m,cs=1; while(scanf("%d",&n)!=EOF){ memset(tree,0,sizeof tree); build(1,n,1); scanf("%d",&m); printf("Case #%d:\n",cs++); while(m--){ int f,x,y; scanf("%d%d%d",&f,&x,&y); if(x>y) swap(x,y); //注意著。 if(f==1){ printf("%lld\n",query(x,y,1,n,1)); }else{ change(x,y,1,n,1); } } printf("\n"); } }