UVa 11992

被bug折磨好久,关于add操作中递归部分一个疏漏,而且测试样例比较弱也看不出来,写代码的时候脑子一定要非常清楚,避免类似低级错误。
一直纠结二位线段树的写法,结果树套树方法纠结很久着手写才发现空间复杂度是根本容不下的。

  • 线段树空间一般是原数组4倍,或者比 数组大小 大的最小2的幂的两倍,这道题是需要利用后一个结论的
  • 虽然这道题不能用来练手树套树,不过思路差不多,一行维护一个线段树,关于add操作是否需要考虑永久化标记,考虑到题目还有set操作,代码思路还是一致为好,对于add的维护有些类似set
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <unordered_map>
using namespace std;

const int INF= 1<<30;
const int maxs= (1<<21)+100;

struct SegY
{
	int l, r;
	int mx, mn, sm;
	int setv, addv;
};
struct SegX
{
	SegY sty[maxs];
	void build(int x, int l, int r)
	{
		if (l > r){
			return;
		}
		sty[x].l= l;
		sty[x].r= r;
		sty[x].mx= sty[x].mn= sty[x].sm= 0;
		sty[x].setv= -1;
		sty[x].addv= 0;
		if (l == r){
			return;
		}

		int mid= (l+r)>>1;
		build(x<<1, l, mid);
		build(x<<1|1, mid+1, r);
	}
	int qMax(const int x, const int L, const int R)
	{
		if (L <= sty[x].l && R >= sty[x].r){
			return sty[x].mx;
		}

		PushD(x);
		int mid= (sty[x].l+sty[x].r)>>1;
		if (R <= mid){
			return qMax(x<<1, L, R);
		} else if (L > mid){
			return qMax(x<<1|1, L, R);
		} else{
			return max(qMax(x<<1, L, R), qMax(x<<1|1, L, R));
		}
	}
	int qMin(const int x, const int L, const int R)
	{
		if (L <= sty[x].l && R >= sty[x].r){
			return sty[x].mn;
		}

		PushD(x);
		int mid= (sty[x].l+sty[x].r)>>1;
		if (R <= mid){
			return qMin(x<<1, L, R);
		} else if (L > mid){
			return qMin(x<<1|1, L, R);
		} else{
			return min(qMin(x<<1, L, R), qMin(x<<1|1, L, R));
		}
	}
	int qSum(const int x, const int L, const int R)
	{
		if (L <= sty[x].l && R >= sty[x].r){
			return sty[x].sm;
		}

		PushD(x);
		int mid= (sty[x].l+sty[x].r)>>1;
		if (R <= mid){
			return qSum(x<<1, L, R);
		} else if (L > mid){
			return qSum(x<<1|1, L, R);
		} else{
			return qSum(x<<1, L, R)+qSum(x<<1|1, L, R);
		}
	}
	void setNd(const int x, const int v)
	{
		sty[x].mx= sty[x].mn= v;
		sty[x].sm= (sty[x].r-sty[x].l+1)*v;
		sty[x].setv= v;
		sty[x].addv= 0;
	}
	void addNd(const int x, const int v)
	{
		sty[x].mx+= v;
		sty[x].mn+= v;
		sty[x].sm+= (sty[x].r-sty[x].l+1)*v;
		sty[x].addv+= v;
	}
	void PushD(int x)
	{
		if (sty[x].l == sty[x].r){
			sty[x].setv= -1;
			sty[x].addv= 0;
			return;
		}
		int lc= x<<1, rc= x<<1|1;
		int setv= sty[x].setv, addv= sty[x].addv;

		if (~setv && addv){
			setv+= addv;
			addv= 0;
		}
		if (~setv){
			setNd(lc, setv);
			setNd(rc, setv);
		} else if (addv){
			addNd(lc, addv);
			addNd(rc, addv);
		}

		sty[x].setv= -1;
		sty[x].addv= 0;
	}
	void PushU(int x)
	{
		if (sty[x].l == sty[x].r){
			return;
		}
		int lc= x<<1, rc= x<<1|1;

		sty[x].mx= max(sty[lc].mx, sty[rc].mx);
		sty[x].mn= min(sty[lc].mn, sty[rc].mn);
		sty[x].sm= sty[lc].sm+sty[rc].sm;
	}
	void set(const int x, const int L, const int R, const int v)
	{
		if (L <= sty[x].l && R >= sty[x].r){
			setNd(x, v);
			return;
		}

		int mid= (sty[x].l+sty[x].r)>>1;
		PushD(x);

		if (L <= mid){
			set(x<<1, L, R, v);
		}
		if (R > mid){
			set(x<<1|1, L, R, v);
		}
		PushU(x);
	}
	void add(const int x, const int L, const int R, const int v)
	{
		if (L <= sty[x].l && R >= sty[x].r){
			addNd(x, v);
			return;
		}

		int mid= (sty[x].l+sty[x].r)>>1;
		PushD(x);

		if (L <= mid){
			add(x<<1, L, R, v);
		}
		if (R > mid){
			add(x<<1|1, L, R, v);
		}
		PushU(x);
	}
}stx[23];
int r, c, m;
int X1, Y1, X2, Y2;

inline void Build()
{
	for (int i= 1; i <= r; ++i){
		stx[i].build(1, 1, c);
	}
}
inline int qMax()
{
	int ret= -INF;
	for (int i= X1; i <= X2; ++i){
		ret= max(ret, stx[i].qMax(1, Y1, Y2));
	}

	return ret;
}
inline int qMin()
{
	int ret= INF;
	for (int i= X1; i <= X2; ++i){
		ret= min(ret, stx[i].qMin(1, Y1, Y2));
	}

	return ret;
}
inline int qSum()
{
	int ret= 0;
	for (int i= X1; i <= X2; ++i){
		ret+= stx[i].qSum(1, Y1, Y2);
	}

	return ret;
}
inline void Set(int v)
{
	for (int i= X1; i <= X2; ++i){
		stx[i].set(1, Y1, Y2, v);
	}
}
inline void Add(int v)
{
	for (int i= X1; i <= X2; ++i){
		stx[i].add(1, Y1, Y2, v);
	}
}

int main(int argc, char const *argv[])
{
	while (3 == scanf("%d%d%d", &r, &c, &m)){
		Build();
		int v, tp;
		while (m--){
			scanf("%d", &tp);
			if (1 == tp){
				scanf("%d%d%d%d%d", &X1, &Y1, &X2, &Y2, &v);
				Add(v);
			} else if (2 == tp){
				scanf("%d%d%d%d%d", &X1, &Y1, &X2, &Y2, &v);
				Set(v);
			} else{
				scanf("%d%d%d%d", &X1, &Y1, &X2, &Y2);
				printf("%d %d %d\n", qSum(), qMin(), qMax());
			}
		}
	}

	return 0;
}
posted @ 2021-09-10 22:35  IdiotNe  阅读(33)  评论(0编辑  收藏  举报