您的位置:首页 > 其它

[kuangbin带你飞]专题七 线段树 H HDU-4027

2017-10-01 20:06 337 查看
题意

2种操作,1:区间里所有数开平方,0:区间和

不能像平时那样用lazy成段更新,因为每个数的更新不是统一的,不是一起增加k,或是变成k,所以成段更新是比较困难的。。

但考虑到数的大小是k<2^64。所以最多开6,7次就能到1了。所以如果一个区间内全是1就不需要更新了,否则更新到叶子节点。判断的方法就是tr[id].sum=r-l+1.区间和为区间大小。

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#define lid (id<<1)
#define rid (id<<1|1)
using namespace std;
const int maxn=100010;
long long  a[maxn];
struct node
{
int l,r;
long long sum;
}tr[maxn*4];
void push_up(int id)
{
tr[id].sum=tr[lid].sum+tr[rid].sum;
}
void build(int id,int l,int r)
{
tr[id].l=l,tr[id].r=r;
if(tr[id].l==tr[id].r) tr[id].sum=a[l];
else{
int mid=(tr[id].l+tr[id].r)>>1;
build(lid,l,mid);
build(rid,mid+1,r);
push_up(id);
}
}
void updata(int id,int l,int r)
{
if(tr[id].l==l && tr[id].r==r && tr[id].sum==r-l+1) return ;
if(tr[id].l==tr[id].r)
{
tr[id].sum=sqrt(tr[id].sum*1.0);
return ;
}
int mid=(tr[id].l+tr[id].r)>>1;
if(r<=mid) updata(lid,l,r);
else if (l>mid) updata(rid,l,r);
else{
updata(lid,l,mid);
updata(rid,mid+1,r);
}
push_up(id);
}
long long query(int id,int l,int r)
{
if(l==tr[id].l && r==tr[id].r) return tr[id].sum;
else{
int mid=(tr[id].l+tr[id].r)>>1;
if(r<=mid) return query(lid,l,r);
else if(l>mid) return query(rid,l,r);
else{
return query(lid,l,mid)+query(rid,mid+1,r);
}
}
}
int main()
{
int n,m,iCase=1;
int t,x,y;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
scanf("%d",&m);
printf("Case #%d:\n",iCase++);
while(m--)
{
scanf("%d%d%d",&t,&x,&y);
if(x>y) swap(x,y);
if(t==0) updata(1,x,y);
else printf("%lld\n",query(1,x,y));
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: