hdu4027 剪枝+用不上懒标记的线段树

https://cn.vjudge.net/problem/HDU-4027

给n个数 

然后两种操作

0操作 把【l,r】的数都开根(向下取整)

1操作 输出【l,r】的区间和

因为这是每个数开根 而不是加上 所以结点没法直接更新 

不同于懒标记  懒标记是把当前结点标记了,同时也更新当前结点的信息  然后直接返回

注意懒标记下面的数据还没更新的!!  但是没关系 如果下次访问到  pushdown会帮我们把上面的懒标记传下去

从而更新  这就是所谓的“懒”  用到时才行动   所以高效

这题解决:全都走到叶节点加

直接更新叶节点 然后靠pushup把上面修正

然而TLE

还需要一个剪枝  我们知道开根  2^63  

开一次2^31     2^15     2^7    2^3      2^1     2^0

也就那么6  、7 次

1开根还是1  就没必要再去开根了   

秒:  如果区间和 比如【2,7】的区间和 若是7-2+1=6  这里面就有6个数
这说明  从rt开始 叶节点都是1 那既然是1 就不用再下去 开根还是1

如       1--3                                         3

     1--2       3              对应的值     2        1

  1       2                                      1    1

所以直接返回 当前结点的这一子树 无需做无用功 

#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<functional>

using namespace std;
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define mem(a, b) memset(a, b, sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
//#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);

const int maxn = 1e5 + 100;

LL sum[4 * maxn];
//int lazy[4* maxn];
inline void pushup(int rt){
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void build(int l, int r, int rt){
	if (l == r){
		scanf("%lld", &sum[rt]);
		return;
	}
	int m = l + (r - l) / 2;
	build(lson);
	build(rson);
	pushup(rt);
}



void update(int L, int R, int l, int r, int rt){
	//因为这是每个数开根 而不是加上 所以结点没法直接更新 
	//解决:全都走到叶节点加
	//直接更新叶节点 然后考pushup把上面修正
	if (l == r){
		sum[rt] = sqrt(sum[rt] * 1.0);//转成long long 相当于向下取整
		return;
	}
	//如果区间和 比如【2,7】的区间和 若是7-2+1=6  这里面就有6个数
	//这说明  从rt开始 叶节点都是1 那既然是1 就不用再下去 开根还是1
	if (L <= l && R >= r && sum[rt] == r - l + 1)
		return;
	int m = l + (r - l ) / 2;
	//pushdown(rt, m - l + 1, r - m);
	if (m >= L)
		update(L, R, lson);
	if (m + 1<= R)
		update(L, R, rson);
	pushup(rt);
}

LL query(int L, int R, int l, int r, int rt){
	if (l >= L && r <= R){
		return sum[rt];
	}
	
	LL res = 0;
	int m = l + (r - l ) / 2;
	if (m >= L)
		res += query(L, R, lson);
	if (m + 1 <= R)
		res += query(L, R, rson);
	return res;
}

int main(){
	int n;
	int cas = 1;
	while (~scanf("%d", &n)){
		mem(sum, 0);
		printf("Case #%d:\n", cas++);
		build(1, n, 1);
		int m;
		scanf("%d", &m);
		int a, b, c;
		while (m--){
			scanf("%d%d%d", &a, &b, &c);
			int f = min(b, c), s = max(b, c);
			if (a == 0)
				update(f, s, 1, n, 1);
			else if (a == 1)
				printf("%lld\n", query(f, s, 1, n, 1));
		}
		puts("");
	}

	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/liangnimahanwei/article/details/82844604