• 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
    ", qSum(), qMin(), qMax());
    			}
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    C语言中标识符的作用域、命名空间、链接属性、生命周期、存储类型
    循环练习
    ArrayList集合

    方法
    表单标签
    HTML基础
    二维数组
    一维数组
    switch选择结构
  • 原文地址:https://www.cnblogs.com/Idi0t-N3/p/15253310.html
Copyright © 2020-2023  润新知