SP2713 GSS4 - Can you answer these queries IV线段树

LINK
题意翻译

「题意」: nnn 个数,和在101810^{18}1018 范围内。

也就是∑ ai ≤ 1018\suma_i\leq~10^{18}∑ ai​ ≤ 1018

现在有「两种」操作

0 x y把区间[x,y][x,y][x,y] 内的每个数开方,下取整

1 x y询问区间[x,y][x,y][x,y] 的每个数的和

「格式」: 有多组数据,数据以EOF结束,对于每组数据,输出数据的序号,每组数据之后输出一个空行。

「注意」: 不保证给出的区间[x,y][x, y][x,y] 有x<=yx <= yx<=y ,如果x>yx>yx>y 请交换xxx ,yyy 。

感谢@Edgration 提供的翻译
输入输出样例
输入 #1

5
1 2 3 4 5
5
1 2 4
0 2 4
1 2 4
0 4 5
1 1 5
4
10 10 10 10
3
1 1 4
0 2 3
1 1 4

输出 #1

Case #1:
9
4
6

Case #2:
40
26

#include<bits/stdc++.h>
using namespace std;
int n;typedef long long ll;
const int N=100010;
struct node
{
ll a,maxn;	
// maxn表示子树的最大值,image 如果最大值是1 那么就不要考虑update 了 好像最大的数字也最大6  次就可以开方成1 大大减少更新时间
void init()
{
	a=maxn=0;
}
}t[N<<2];
void up(int rt)
{
	t[rt].a=t[rt<<1|1].a+t[rt<<1].a;
	t[rt].maxn=max(t[rt<<1|1].maxn,t[rt<<1].maxn);
}
void build(int l,int r,int rt)
{
	t[rt].init();
	if(l==r)
	{
		ll a;scanf("%lld",&a);
		t[rt]=(node){a,a};return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	up(rt); 
}
void update(int L,int R,int l,int r,int rt)
{
	if(t[rt].maxn<=1) return ;//这种情况取sqrt无意义了
	if(l==r)
	{
		t[rt].a=sqrt(t[rt].a );
		t[rt].maxn=t[rt].a;
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=L) update(L,R,l,mid,rt<<1);
	if(mid<R) update(L,R,mid+1,r,rt<<1|1);
	up(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
	if(l>=L&&r<=R)
	{
		return t[rt].a ;
	}
	int mid=(l+r)>>1; ll s=0;
	if(mid>=L) s+=query(L,R,l,mid,rt<<1);
	if(mid<R) s+=query(L,R,mid+1,r,rt<<1|1);
	return s;
}

int main()
{
	int cas=0;
	while(~scanf("%d",&n))
	{
		build(1,n,1);
		int m;
		scanf("%d",&m);
		printf("Case #%d:\n",++cas);
		while(m--)
		{
			int op,l,r;scanf("%d%d%d",&op,&l,&r);
			if(l>r) swap(l,r);
			if(op==1)
			{
			printf("%lld\n",query(l,r,1,n,1));	
			}else 
			{
				update(l,r,1,n,1);
			}
		}
	}
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值