BZOJ 3211-花神游历各国(线段树)

3211: 花神游历各国

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 3476  Solved: 1288
[ Submit][ Status][ Discuss]

Description

Input

Output

每次x=1时,每行一个整数,表示这次旅行的开心度

Sample Input

4

1 100 5 5

5

1 1 2

2 1 2

1 1 2

2 2 3

1 1 4

Sample Output

101

11

11

HINT


这道题之前在qscoj上写过,一模一样的,乍一看感觉单点更新会超时(其实真的会),但是你会发现有许多不必要的操作,

比如说当一个数的值小于等于1时,再对它开根号就没有意义了,所以开一个最大值数组标记一下区间最大值即可。。。。

假如该区间最大值<=1时,则该区间就没必要更新了,还是很好想的是吧


#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long  ll;
#define inf 10000000
#define mod 1000000007 
#define  maxn  800005
#define  eps 1e-10
ll sum[maxn],maxs[maxn];
void build(int id,int l,int r)
{
	if(l==r)
	{
		scanf("%lld",&sum[id]);
		maxs[id]=sum[id];
		return;
	}
	int m=(l+r)/2;
	if(l<=m)
		build(id*2,l,m);
	if(r>m)
		build(id*2+1,m+1,r);
	sum[id]=sum[id*2]+sum[id*2+1];
	maxs[id]=max(maxs[id*2],maxs[id*2+1]);
}
void updata(int id,int l,int r,int L,int R)
{
	if(maxs[id]<=1)
		return;
	if(l==r)
	{
		sum[id]=sqrt(sum[id]);
		maxs[id]=sum[id];
		return;
	}
	int m=(l+r)/2;
	if(L<=m)
		updata(id*2,l,m,L,R);
	if(R>m)
		updata(id*2+1,m+1,r,L,R);
	sum[id]=sum[id*2]+sum[id*2+1];
	maxs[id]=max(maxs[id*2],maxs[id*2+1]);
}
ll query(int id,int l,int r,int L,int R)
{
	if(L<=l && R>=r)
		return sum[id];
	ll ans=0;int m=(l+r)/2;
	if(L<=m)
		ans+=query(id*2,l,m,L,R);
	if(R>m)
		ans+=query(id*2+1,m+1,r,L,R);
	return ans;
}
int  main(void)
{
	int n,q,x,y,z;
	scanf("%d",&n);
	build(1,1,n);
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d%d%d",&x,&y,&z);
		if(x==1)
			printf("%lld\n",query(1,1,n,y,z));
		else
			updata(1,1,n,y,z);
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值