bzoj3211花神游历各国 线段树

题目链接:戳这里

3211: 花神游历各国

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 4119  Solved: 1504
[ 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

对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9


Source

一道还算简单的线段树。

看到题目中的区间操作和查询很容易让人想到线段树,但区间开方好像不满足区间加和性质?

所以我们必须修改到每个叶节点上,但这么做就会TLE。

观察数据:因为是向下取整,所以经过几次操作后就会有区间变成1,显然全是1的区间我们就没必要继续修改下去了,这样就能大大减少复杂度。

对于线段树的每个节点,维护一个lazy或区间最大值,当lazy大于6或区间最大值<=1的时候就直接返回。

代码:

#include<bits/stdc++.h>
#define maxn 100010 
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
int n,ql[maxn];
int m;
LL sum[maxn*4];
int lazy[maxn*4];
void pushup(int id)
{
	sum[id]=sum[id<<1]+sum[id<<1|1];
	return;
}
void build(int id,int l,int r)
{
	if(l==r)
	{
		sum[id]=ql[l];
		return;
	}
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	pushup(id);
}
void update(int id,int ql,int qr,int l,int r)
{
	if(l>=ql && r<=qr)
	{
		lazy[id]++;
		if(l==r)
		{
			sum[id]=sqrt(sum[id]);
			return;
		}
	}
	int mid=(l+r)>>1,lson=(id<<1),rson=(id<<1|1);
	if(lazy[lson]<6 && ql<=mid) update(lson,ql,qr,l,mid);
	if(lazy[rson]<6 && qr>mid) update(rson,ql,qr,mid+1,r);
	pushup(id);
	return;
}
LL query(int id,int ql,int qr,int l,int r)
{
	if(l>=ql && r<=qr)
	return sum[id];
	LL ans=0;
    int mid=(l+r)>>1;
    if(ql<=mid) ans+=query(id<<1,ql,qr,l,mid);
    if(qr>mid) 	ans+=query(id<<1|1,ql,qr,mid+1,r);
    return ans;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	ql[i]=read();
	build(1,1,n);
	m=read();
	for(int i=1;i<=m;i++)
	{
		int f=read(),l=read(),r=read();
		if(f==1) printf("%lld\n",query(1,l,r,1,n));
		if(f==2) update(1,l,r,1,n);
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值