hdu 4027 Can you answer these queries?
题意:将题目的背景去掉,简单的说,就是每一次对一个区间的所有值都分别做一次求平方根的运算,就是将那个值改为它的平方根的值,每次再询问一段区间内的总和
分析:很明显的用线段树来做,不过明显的对线段树还是不熟悉,一开始将每一步update操作都更新到具体的每一个点了,没有任何技巧,直接TLE;很明显,如果每一步都必须更新的具体每一个点的话,就是一个
O(n)复杂度的操作了,这个对使用线段树来说,没太大意义了。
这题目而言,我们发现,任何一个2^63次方以内的数,开根号都至多开八次,也就是,多次询问操作之后,很多都已经不需要update了,所以,只需要在每一个节点中增加一个域,用来标记该区间是否已经全部更新到0或者1了,若满足条件,则不需要更新了
#include<iostream> #include<math.h> #define MAXN 100002 using namespace std; __int64 c[MAXN]; struct node { int l,r; __int64 sum; bool d; }p[MAXN*4]; void bulid( int s, int t, int k) { p[k].l=s;p[k].r=t; if (t==s) { p[k].sum=c[s]; p[k].d=(c[s]<=1LL); return ; } int kl=k<<1,kr=kl+1,mid=(s+t)>>1; bulid(s,mid,kl); bulid(mid+1,t,kr); p[k].sum=p[kl].sum+p[kr].sum; p[k].d=p[kl].d && p[kr].d; } void decr( int k, int l, int r) { if (p[k].l>r||p[k].r<l) return ; if (p[k].d) return ; if (p[k].r==p[k].l) { p[k].sum=( __int64 )( sqrt (( double )p[k].sum)); p[k].d=(p[k].sum<=1LL); return ; } int kl=k<<1,kr=kl+1; decr(kl,l,r); decr(kr,l,r); p[k].sum=p[kr].sum+p[kl].sum; p[k].d=p[kr].d && p[kl].d; } __int64 query( int k, int l, int r) { if (p[k].l>r||p[k].r<l) return 0; if (p[k].l>=l&&p[k].r<=r) return p[k].sum; int kl=k<<1,kr=kl+1; return query(kl,l,r)+query(kr,l,r); } int main() { int n,m,a,b,cas=0,k; while ( scanf ( "%d" ,&n)==1) { for ( int i=1;i<=n;i++) scanf ( "%I64d" ,&c[i]); bulid(1,n,1); printf ( "Case #%d:\n" ,++cas); scanf ( "%d" ,&m); while (m--) { scanf ( "%d %d %d" ,&k,&a,&b); if (a>b) { int temp=a;a=b;b=temp;} if (k==0) decr(1,a,b); else printf ( "%I64d\n" ,query(1,a,b)); } printf ( "\n" ); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步