HDU - 4027 -- Can you answer these queries?【线段树区间更新 + 剪枝】

题意

有n个敌方战舰,每一艘战列舰都标明其耐力值。对于我们的秘密武器的每一次攻击,它都可以通过使战舰的耐久力减到原耐久力值的平方根来降低其连续的耐久力。现在给出m个查询,每个查询包含T, X, Y
T = 1;查询x到y战舰的耐力总值
T = 0;x到y的每搜战舰的耐力值减到原来的平方根

思路

当每个战舰的耐力值减少到1时,就不会再减少了,因为1的平方根就为1. 所以在区间修改的时候加一个判断条件即可。
还有一个坑点:当a > b时查出来的是 0,因为没这种区间,所以需要交换。

AC代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define IOS ios::sync_with_stdio(false)
#define ls  (rt << 1)
#define rs	(rt << 1 | 1)
typedef long long ll;
const int maxn = 100100;
ll sum[maxn << 2], arr[maxn];
void pushUp(int rt){
	sum[rt] = sum[ls] + sum[rs];
}
void build(int rt, int l, int r){
	if (l == r){
		sum[rt] = arr[l];
		return;
	}
	int m = (l + r) >> 1;
	build(ls, l, m);
	build(rs, m + 1, r);
	pushUp(rt);
}
void update(int rt, int l, int r, int L, int R){
	//剪枝:如果当前耐力值变成1,后面就不在变化。 成功踩坑
	if (sum[rt] == r - l + 1)	return; 
	if (l == r){
		sum[rt] = (ll)sqrt(sum[rt]);
		return;
	}
	int m = (l + r) >> 1;
	if (L <= m)		update(ls, l, m, L, R);
	if (m < R)		update(rs, m + 1, r, L, R);
	pushUp(rt);
}
ll query(int rt, int l, int r, int L , int R){
	if (L <= l && r <= R){
		return sum[rt];
	}
	int m = (l + r) >> 1;
	ll res = 0;
	if (L <= m)		res += query(ls, l, m, L, R);
	if (m < R)		res += query(rs, m + 1, r, L, R);
	return res;
}
void solve(){
	int n, m, cnt = 0;
	while (~scanf("%d", &n)){
		for (int i = 1; i <= n; ++i)	scanf("%lld", &arr[i]);
		build(1, 1, n);
		int k, l, r;
		printf("Case #%d:\n", ++cnt);
		scanf("%d", &m);
		while (m--){
			scanf("%d%d%d", &k, &l, &r);
			//再次踩坑
			if (l > r)	swap(l, r);
			if (k == 0){
				update(1, 1, n, l, r);
			} else {
				ll ans = query(1, 1, n, l, r);
				printf("%lld\n", ans);
			}
		}
		puts("");
	}
}
int main(){
	solve();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值