1550:花神游历各国

文章展示了如何用动态规划和二叉树数据结构解决BZOJ3211中的问题,计算花神根据路线调整后不同旅行阶段的开心值。
摘要由CSDN通过智能技术生成

时间限制: 1000 ms         内存限制: 524288 KB
提交数: 2830     通过数: 926

【题目描述】

原题来自:BZOJ 3211

花神喜欢步行游历各国,顺便虐爆各地竞赛。花神有一条游览路线,它是线型的,也就是说,所有游历国家呈一条线的形状排列,花神对每个国家都有一个喜欢程度(当然花神并不一定喜欢所有国家)。

每一次旅行中,花神会选择一条旅游路线,它在那一串国家中是连续的一段,这次旅行带来的开心值是这些国家的喜欢度的总和,当然花神对这些国家的喜欢程序并不是恒定的,有时会突然对某些国家产生反感,使他对这些国家的喜欢度 δδ 变为 δ√δ(可能是花神虐爆了那些国家的 OI,从而感到乏味)。

现在给出花神每次的旅行路线,以及开心度的变化,请求出花神每次旅行的开心值。

【输入】

第一行是一个整数 N�,表示有 N� 个国家;

第二行有 N� 个空格隔开的整数,表示每个国家的初始喜欢度 δiδ� ;

第三行是一个整数 M�,表示有 M� 条信息要处理;

第四行到最后,每行三个整数 x,l,r�,�,�,当 x=1�=1 时询问游历国家 l� 到 r� 的开心值总和,就是 ∑ri=lδi∑�=��δ� ,当 x=2�=2 时国家 l� 到 r� 中每个国家的喜欢度 δiδ�变为 δi−−√δ� 。

【输出】

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

【输入样例】

4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4

【输出样例】

101
11
11

【提示】

数据范围与提示:

对于全部数据,1≤n≤105,1≤m≤2×105,1≤l≤r≤n,0≤δi≤1091≤�≤105,1≤�≤2×105,1≤�≤�≤�,0≤δ�≤109 。

注:建议使用 sqrt���� 函数,且向下取整。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
ll sum[maxn*4],ma[maxn*4],num[maxn];
void build(int l,int r,int root){
	if(l==r){
		sum[root]=ma[root]=num[l];return;
	}
	int m=l+r>>1;
	build(l,m,root<<1);
	build(m+1,r,root<<1|1);
	sum[root]=sum[root<<1]+sum[root<<1|1];
	ma[root]=max(sum[root<<1],sum[root<<1|1]);
}
void update(int ul,int ur,int l,int r,int root){
	if(ma[root]==1||ma[root]==0) return;
	if(l==r){ma[root]=sum[root]=sqrt(sum[root]);return;}
	int m=l+r>>1;
	if(ul<=m) update(ul,ur,l,m,root<<1);
	if(m<ur) update(ul,ur,m+1,r,root<<1|1);
	sum[root]=sum[root<<1]+sum[root<<1|1];
	ma[root]=max(ma[root<<1],ma[root<<1|1]);
}
ll query(int ql,int qr,int l,int r,int root){
	if(ql<=l&&r<=qr) return sum[root];
	int m=l+r>>1;
	ll ans=0;
	if(ql<=m) ans+=query(ql,qr,l,m,root<<1);
	if(m<qr) ans+=query(ql,qr,m+1,r,root<<1|1);
	return ans;
}
int main()
{
    ll n,m;scanf("%lld",&n);
    for( int i=1; i<=n; i++ ) scanf("%lld",&num[i]);
    build(1,n,1);
    scanf("%lld",&m);
    for( int i=0; i<m; i++ ){
    	ll op,a,b;scanf("%lld %lld %lld",&op,&a,&b);
    	if(op==1) printf("%lld\n",query(a,b,1,n,1));
    	else update(a,b,1,n,1);
	}
	return 0;
}

请给个关注和赞赞吧~~~球球了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值