hdu4027

这道题之前在camp的时候听人讲过,因为根号运算n衰减的很快,所以在极少数的操作内它就会变成1,所以当整个区间内的值都变成1时直接返回,反之暴力更新叶子结点就好

#include 
#include 
#include 
using namespace std;

typedef long long ll;
const int N = 100100;

ll sum[N * 4];

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) >> 1;
	build(l, m, rt << 1);
	build(m + 1, r, rt << 1 | 1);
	pushup(rt);
}
void update(int L, int R, int l, int r, int rt){
	if(l == r){
		sum[rt] = sqrt(sum[rt]);
		return ;
	}
	if(L <= l && R >= r && sum[rt] == r - l + 1)
		return ;
	int m = (l + r) >> 1;
	if(L <= m)
		update(L, R, l, m, rt << 1);
	if(R > m)
		update(L, R, m + 1, r, rt << 1 | 1);
	pushup(rt);
}
ll query(int L, int R, int l, int r, int rt){
	if(L <= l && r <= R)
		return sum[rt];
	int m = (l + r) >> 1;
	ll s = 0;
	if(L <= m)
		s += query(L, R, l, m, rt << 1);
	if(R > m)
		s += query(L, R, m + 1, r, rt << 1 | 1);
	return s;
}
int main(){
	int n, m, cas = 0;
	while(~ scanf("%d", &n)){
		build(1, n, 1);
		scanf("%d", &m);
		int a, b, c;
		printf("Case #%d:\n", ++ cas);
		while(m --){
			scanf("%d %d %d", &a, &b, &c);
			int bb = min(b, c), cc = max(b, c);
			if(a)
				printf("%lld\n", query(bb, cc, 1, n, 1));
			else
				update(bb, cc, 1, n, 1);
		}
		printf("\n");
	}
	return 0;
}

 

你可能感兴趣的:(hdu4027)