POJ - 3264

线段树。

#include <cstdio>
#include <cstring>
#define isInside(L, R, u, v) (u <= L && R <= v)
#define isOutside(L, R, u, v) (R < u || v < L)

const int MAXN = 2e5 + 100;
typedef long long ll;

typedef struct Seg{
	ll p[MAXN], seg[MAXN * 4], lazy[MAXN * 4], min[MAXN * 4], max[MAXN * 4];
	ll Min(ll x, ll y){
		return x <= y ? x : y;
	}
	ll Max(ll x, ll y){
		return x >= y ? x : y;
	}
	void clear(){
		memset(lazy, 0, sizeof(lazy));
		memset(seg, 0, sizeof(seg));
		memset(min, 0, sizeof(min));
		memset(max, 0, sizeof(max));
	}
	void push_up(int pos){
		seg[pos] = seg[pos << 1] + seg[pos << 1 | 1];
		min[pos] = Min(min[pos << 1], min[pos << 1 | 1]);
		max[pos] = Max(max[pos << 1], max[pos << 1 | 1]);
	}
	void push_down(int pos, int L, int R){
		if(lazy[pos]){
			seg[pos] += lazy[pos] * (R - L + 1);
			min[pos] += lazy[pos];
			max[pos] += lazy[pos];
			lazy[pos << 1] = lazy[pos << 1 | 1] = lazy[pos];
			lazy[pos] = 0;
		}
	}
	void build(int cur, int L, int R){
		if(L > R)	return;
		if(L == R){
			seg[cur] = p[L];
			min[cur] = p[L];
			max[cur] = p[L];
			//printf("(%d, %d), (%lld, %lld, %lld)\n", L, R, seg[cur], min[cur], max[cur]);
			return;
		}
		int mid = L + (R - L) / 2;
		build(cur << 1, L, mid);
		build(cur << 1 | 1, mid + 1, R);
		push_up(cur);
		//printf("(%d, %d), (%lld, %lld, %lld)\n", L, R, seg[cur], min[cur], max[cur]);
	}
	void maintain(int cur, int L, int R, int u, int v, ll value){
		if(isOutside(L, R, u, v))	return;
		int mid = L + (R - L) / 2;
		if(isInside(L, R, u, v)){
			lazy[cur] = value;	return;
		}
		maintain(cur << 1, L, mid, u, v, value);
		maintain(cur << 1 | 1, mid + 1, R, u, v, value);
	}
	ll query(int cur, int L, int R, int u, int v){
		if(isOutside(L, R, u, v))	return 0;
		int mid = L + (R - L) / 2;
		push_down(cur, L, R);
		if(isInside(L, R, u, v))	return seg[cur];
		ll res = 0;
		res += query(cur << 1, L, mid, u, v);
		res += query(cur << 1 | 1, mid + 1, R, u, v);
		return res;	
	}
	ll max_query(int cur, int L, int R, int u, int v){
		if(isOutside(L, R, u, v))	return 0;
		int mid = L + (R - L) / 2;
		push_down(cur, L, R);
		if(isInside(L, R, u, v))	return max[cur];
		ll res = 0;
		res = Max(res, max_query(cur << 1, L, mid, u, v));
		res = Max(res, max_query(cur << 1 | 1, mid + 1, R, u, v));
		return res;	
	}
	ll min_query(int cur, int L, int R, int u, int v){
		if(isOutside(L, R, u, v))	return 1e9;
		int mid = L + (R - L) / 2;
		push_down(cur, L, R);
		if(isInside(L, R, u, v))	return min[cur];
		ll res = 1e9;
		res = Min(res, min_query(cur << 1, L, mid, u, v));
		res = Min(res, min_query(cur << 1 | 1, mid + 1, R, u, v));
		return res;	
	} 
}Seg;

int n, m;
Seg segment;

int main(void)
{
	while(~scanf("%d%d", &n, &m)){
		segment.clear();
		for(int i = 1; i <= n; i++)	scanf("%lld", &segment.p[i]);
		segment.build(1, 1, n);
		while(m--){
			int u, v;	scanf("%d%d", &u, &v);
			//printf("(%lld, %lld)\n", segment.max_query(1, 1, n, u, v), segment.min_query(1, 1, n, u, v));
			printf("%lld\n", segment.max_query(1, 1, n, u, v) - segment.min_query(1, 1, n, u, v));
		}
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值