Can you answer these queries? HDU

来源:互联网 发布:海尔的大数据营销案例 编辑:程序博客网 时间:2024/06/17 10:30

点击打开链接

题意:给定100000个数,两种操作,0 i j表示将i j这段的数字都开根号(向下取整),1 i j表示查询i j之间的所有值

的和。。。(所有的和都不超过64位)..

思路: 这是一个线段树单点更新的题...因为都开平方根啊,,,区间没法更新了吧...

但是这个题有一个优化,就是当a[i]的值小于等于1时就不需要下次再开方了,直接标记他,也是懒人标记的用法,

然后往上回溯,不是往下了,回溯的时候 父节点等于左右子树laz的与,也就是表示了当他下面的左右子树都被标记了下次

在需要平方根时下面就不用再开了 因为1开平方根还是他本身,而且在递归查询的时候 如果左子树laz了 左子树就不需要

去更改了,同理右子树也是如此.

#include<bits/stdc++.h>using namespace std;const int maxn=1e6+10;typedef long long ll;int n,m;ll a[maxn],t[maxn],laz[maxn];void pushup(int d){t[d]=t[2*d]+t[2*d+1];laz[d]=laz[2*d]&&laz[2*d+1];return ;}void build(int l,int r,int d){if(l==r){t[d]=a[l];laz[d]=0;return ;}int mid=(l+r)/2;build(l,mid,2*d);build(mid+1,r,2*d+1);pushup(d);return ;}ll query(int l,int r,int L,int R,int d){if(L<=l&&r<=R){return t[d];}int mid=(l+r)/2;ll ans=0;if(L<=mid)ans+=query(l,mid,L,R,2*d);if(R>mid)ans+=query(mid+1,r,L,R,2*d+1);return ans;}void update(int l,int r,int d,int L,int R){if(l==r){t[d]=sqrt(t[d]*1.0);if(t[d]<=1)laz[d]=1;return ;}int mid=(l+r)/2;if(L<=mid&&!laz[d]){update(l,mid,2*d,L,R);}if(R>mid&&!laz[d]){update(mid+1,r,2*d+1,L,R);}pushup(d);return ;}int main(){ll str,x,y;int k=1;while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++)scanf("%lld",&a[i]);build(1,n,1);scanf("%d",&m);printf("Case #%d:\n",k++);while(m--){scanf("%lld%lld%lld",&str,&x,&y);if(x>y)swap(x,y);if(str){printf("%lld\n",query(1,n,x,y,1));}else{update(1,n,1,x,y);}}puts("");}return 0;}

0 0
原创粉丝点击