1. 程式人生 > >hdu4027 剪枝+用不上懶標記的線段樹

hdu4027 剪枝+用不上懶標記的線段樹

給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;
}