您的位置:首页 > 其它

bzoj 3211: 花神游历各国

2016-05-14 21:04 405 查看

直接写题解吧。。。

题目这么长,其实就是2个操作:

1.询问L,R中的各个数之和

2.将L,R中的每个数x,将x修x1/2,向下取整。。

我们其实可以发现1000000000中的数修改不了几次就会变成1

那么直接暴力修改,若一段区间内的数全部<=1也就不用再改下去了。。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
#define p1 (p<<1)
#define p2 (p<<1|1)
const int N=100005;
int n,m,i,p,x,y,a
,add[N<<2];
long long ans,t[N<<2];
void build(int l,int r,int p)
{
if(l==r)
{
t[p]=a[l];
if(a[l]<=1) add[p]=1;else add[p]=0;
return;
}
int mid=(l+r)>>1;
build(l,mid,p1);
build(mid+1,r,p2);
t[p]=t[p1]+t[p2];
add[p]=add[p1]&add[p2];
}
void update(int l,int r,int x,int y,int p)
{
if(add[p]) return;
if(l==r)
{
t[p]=(int)(sqrt(t[p]));
if(t[p]<=1) add[p]=1;
return;
}
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,y,p1);
if(y>mid) update(mid+1,r,x,y,p2);
add[p]=add[p1]&add[p2];
t[p]=t[p1]+t[p2];
}
void solve(int l,int r,int x,int y,int p)
{
if(x<=l&&r<=y)
{
ans+=t[p];
return;
}
int mid=(l+r)>>1;
if(x<=mid) solve(l,mid,x,y,p1);
if(y>mid) solve(mid+1,r,x,y,p2);
}
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&x,&y);
if(p==1)
{
ans=0;
solve(1,n,x,y,1);
printf("%lld\n",ans);
} else
update(1,n,x,y,1);
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: