http://acm.hdu.edu.cn/showproblem.php?pid=4027
线段树成段更新的题目,开方次数有限,一个区间都是1就lazy。
仿hh风格的线段树,真漂亮啊
View Code
#include <iostream> #include <cmath> using namespace std ; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100002 ; typedef __int64 LL ; LL sum[maxn<<2] ; int lazy ; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1] ; } void pushdown(int rt,int m)//区间上的点都到1,不进行更新 { if(sum[rt]==m) lazy=1 ; else lazy=0 ; } void build(int l,int r,int rt) { if(l==r) { scanf("%I64d",&sum[rt]) ; return ; } int m=(l+r)>>1 ; build(lson) ; build(rson) ; pushup(rt) ; } void update(int L,int R,int l,int r,int rt) { if(l==r) { sum[rt]=LL(sqrt((double)sum[rt])) ; return ; } pushdown(rt,r-l+1) ; if(lazy) return ; int m=(l+r)>>1 ; if(L<=m) update(L,R,lson) ; if(R>m) update(L,R,rson) ; pushup(rt) ; } LL query(int L,int R,int l,int r,int rt) { if(L<=l && R>=r){ return sum[rt] ; } int m=(l+r)>>1 ; LL ans=0 ; if(L<=m) ans+=query(L,R,lson) ; if(R>m) ans+=query(L,R,rson) ; return ans ; } int main() { int n ; int nCase=1 ; while(~scanf("%d",&n)) { build(1,n,1) ; char op[2] ; int m ; scanf("%d",&m) ; printf("Case #%d:\n",nCase++) ; while(m--) { int a,b ; lazy=0 ; scanf("%s%d%d",op,&a,&b) ; if(a>b)a^=b^=a^=b ; if(op[0]=='0') update(a,b,1,n,1) ; else printf("%I64d\n",query(a,b,1,n,1)) ; } putchar('\n') ; } return 0 ; }