UVa 11992 Fast Matrix Operations(线段树双懒操作,二维转一维)

题意:给个r*c的矩形,三种操作,将一个子矩形权值+v,将一个子矩阵权值赋值为v,查询一个子矩阵sum,max,min。起初矩阵权值为0,保证r<=20,r*c<=1e6,操作次数不超过10000

链接:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697

题解:将二维转一维,设当前点为(x,y),则它在线段树上的点为(x-1)*c+y,由于行不超过20行,不妨枚举每一行,去操作。对于一维的线段树,要进行赋值,加法,查询sum,max,min的操作。设两个懒操作变量a,b,a表示赋值的,b表示加法的。当进行赋值操作时,b清0,a+=v;当进行加法操作时,如果a>0,则a+=v,否则b+=v;任何操作时,处理sum,max,min,处理sum时不要忘记乘上区间长度。注意在懒操作和update函数都要进行如上操作。写一个种树、两个更值、三个查询函数。

代码

//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline ll readLL(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int r, c, m;
#define MAXN 1000010

#define lch id<<1
#define rch id<<1|1
#define mid ((l+r)>>1)
struct Segment_Tree{
    ll max, min, sum;
    ll fu, jia;
    int len;
}tree[MAXN << 2];
inline void plant_tree(int id,int l,int r){
    tree[id].max = tree[id].min = tree[id].sum = 0;
    tree[id].fu = tree[id].jia = 0;
    tree[id].len = r - l + 1;
    if(l == r) return;
    plant_tree(lch, l, mid);
    plant_tree(rch, mid + 1, r);
}
void pullup(int id){
    tree[id].sum = tree[lch].sum + tree[rch].sum;
    tree[id].max = max(tree[lch].max, tree[rch].max);
    tree[id].min = min(tree[lch].min, tree[rch].min);
}
void pushdown(int id){
    if(tree[id].fu > 0){
        tree[lch].fu = tree[id].fu;
        tree[lch].jia = 0;
        tree[lch].max = tree[lch].min = tree[id].fu;
        tree[lch].sum = tree[id].fu * tree[lch].len;

        tree[rch].fu = tree[id].fu;
        tree[rch].jia = 0;
        tree[rch].max = tree[rch].min = tree[id].fu;
        tree[rch].sum = tree[id].fu * tree[rch].len;

        tree[id].fu = 0;
    }
    else if(tree[id].jia > 0){
        //bug
        if(tree[lch].fu > 0) tree[lch].fu += tree[id].jia;
        else tree[lch].jia += tree[id].jia;
        tree[lch].sum += tree[id].jia * tree[lch].len;
        tree[lch].max += tree[id].jia;
        tree[lch].min += tree[id].jia;

        if(tree[rch].fu > 0) tree[rch].fu += tree[id].jia;
        else tree[rch].jia += tree[id].jia;
        tree[rch].sum += tree[id].jia * tree[rch].len;
        tree[rch].max += tree[id].jia;
        tree[rch].min += tree[id].jia;

        tree[id].jia = 0;
    }
}
inline void update_fu(int id,int ql,int qr,int l,int r,ll v){
    if(ql == l && qr == r){
        tree[id].fu = v;
        tree[id].jia = 0;
        tree[id].min = tree[id].max = v;
        tree[id].sum = v * tree[id].len;
        return;
    }
    pushdown(id);

    if(qr <= mid) update_fu(lch, ql, qr, l, mid, v);
    else if(mid < ql) update_fu(rch, ql, qr, mid + 1, r, v);
    else update_fu(lch, ql, mid, l, mid, v), update_fu(rch, mid + 1, qr, mid + 1, r, v);

    pullup(id);
}
inline void update_jia(int id,int ql,int qr,int l,int r,ll v){
    if(ql == l && qr == r){
        if(tree[id].fu > 0) tree[id].fu += v;
        else tree[id].jia += v;
        tree[id].sum += v * tree[id].len;
        tree[id].max += v;
        tree[id].min += v;
        return;
    }
    pushdown(id);

    if(qr <= mid) update_jia(lch, ql, qr, l, mid, v);
    else if(mid < ql) update_jia(rch, ql, qr, mid + 1, r, v);
    else update_jia(lch, ql, mid, l, mid, v), update_jia(rch, mid + 1, qr, mid + 1, r, v);

    pullup(id);
}
inline ll query_min(int id,int ql,int qr,int l,int r){
    if(ql == l && qr == r) return tree[id].min;
    pushdown(id);

    if(qr <= mid) return query_min(lch, ql, qr, l, mid);
    else if(mid < ql) return query_min(rch, ql, qr, mid + 1, r);
    else return min(query_min(lch, ql, mid, l, mid), query_min(rch, mid + 1, qr, mid + 1, r));
}
inline ll query_max(int id,int ql,int qr,int l,int r){
    if(ql == l && qr == r) return tree[id].max;
    pushdown(id);

    if(qr <= mid) return query_max(lch, ql, qr, l, mid);
    else if(mid < ql) return query_max(rch, ql, qr, mid + 1, r);
    else return max(query_max(lch, ql, mid, l, mid), query_max(rch, mid + 1, qr, mid + 1, r));
}
inline ll query_sum(int id,int ql,int qr,int l,int r){
    if(ql == l && qr == r) return tree[id].sum;
    pushdown(id);

    if(qr <= mid) return query_sum(lch, ql, qr, l, mid);
    else if(mid < ql) return query_sum(rch, ql, qr, mid + 1, r);
    else return query_sum(lch, ql, mid, l, mid) + query_sum(rch, mid + 1, qr, mid + 1, r);
}
int f(int x,int y){
    return (x - 1) * c + y;
}
int main(){
    //freopen("/Users/peteryuanpan/data.txt","r",stdin);

    while(~scanf("%d%d%d",&r,&c,&m)){

        int n = r * c;
        plant_tree(1, 1, n);

        for(int im = 1; im <= m; im++){
            int ty = read();
            int x1, y1, x2, y2;
            ll v;
            if(ty == 1){
                x1 = read(), y1 = read();
                x2 = read(), y2 = read();
                v = readLL();
                for(int i = x1; i <= x2; i++){
                    int l = f(i, y1), r = f(i, y2);
                    update_jia(1, l, r, 1, n, v);
                }
            }
            else if(ty == 2){
                x1 = read(), y1 = read();
                x2 = read(), y2 = read();
                v = readLL();
                for(int i = x1; i <= x2; i++){
                    int l = f(i, y1), r = f(i, y2);
                    update_fu(1, l, r, 1, n, v);
                }
            }
            else if(ty == 3){
                ll sum = 0, maxi = -1e18, mini = 1e18;
                x1 = read(), y1 = read();
                x2 = read(), y2 = read();
                for(int i = x1; i <= x2; i++){
                    int l = f(i, y1), r = f(i, y2);
                    sum += query_sum(1, l, r, 1, n);
                    maxi = max(maxi, query_max(1, l, r, 1, n));
                    mini = min(mini, query_min(1, l, r, 1, n));
                    //printf("i = %d l=%d r=%d %lld %lld %lld\n",i,l,r,sum,mini,maxi);
                }

                printf("%lld %lld %lld\n",sum,mini,maxi);
            }
        }
    }

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-26 20:11:30

UVa 11992 Fast Matrix Operations(线段树双懒操作,二维转一维)的相关文章

UVa 11992 Fast Matrix Operations (线段树)

Fast Matrix Operations Description There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x, y) where 1 ≤ x ≤ r, 1 ≤ y ≤ c. Initially, all the elements are zero. You need to handle four kinds

UVA 11992 - Fast Matrix Operations

Fast Matrix Operations There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operati

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 ) 这是大白书上的例题,一直放着没有去A掉,这是一道线段树区间修改的好题. 线段树中需要维护三个域 ,max, min, sum,也就是区间最大值,最小值,区间和 题目大意: r 行 c 列 的全0矩阵,支持三个操作 1 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素增加v 2 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素设为v 3 x1 y1

UVA 11992(Fast Matrix Operations-线段树区间加&amp;改)[Template:SegmentTree]

Fast Matrix Operations There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operati

[uva11992]Fast Matrix Operations(多延迟标记,二维线段树,区间更新)

题目链接:https://vjudge.net/problem/UVA-11992 题意:n*m的矩阵,每次对一个子矩阵操作,有三种操作:加x,设置为x,查询.查询返回子矩阵和.最小值.最大值 n很小(<=20),所以可以开20棵线段树,每次操作按行更新. 特别小心put和add两个延迟标记,坑老惨了. put初始化-1最简单的坑,略过. build的时候要每一个节点都要clear,不能只clear叶子.因为会有直接差没操作的子矩阵(因为初始化都是0). 数组开大... add的话,什么都不用管

线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using namespace std; #define lson l, mid, o << 1 #define rson mid + 1, r, o << 1 | 1 typedef long long ll; const int INF = 0x3f3f3f3f; const int N =

UVA 11992 Fast Matrix Operations (降维)

题意:对一个矩阵进行子矩阵操作. 元素对多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作. 一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测没有),如果判断一下然后建树复杂度是min(RlogC,ClogR). 代码中结点没有保存l和r,而且询问是保存在全局变量中,这样做比较省空间.但是也有缺点,比如推区间结点数量的时候会麻烦一点. #include<bits/stdc++.h> using namespace std; const

UVA11992 - Fast Matrix Operations(线段树区间修改)

题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v 把由x1,y1, x2, y2构成的子矩阵里的每个元素都加上v. 2 x1, y1, x2, y2, v 把这个子矩阵的每个元素都修改为v. 3 x1, y1, x2, y2 查询这个子矩阵的元素之和,和这些元素的最大值和最小值. 解题思路:因为矩阵的行最多20行,所以可以将这个矩阵的元素构建一棵线段树,每个节点都有三个附加信息:sum,Max_num, Min_num.然后修改查询

UVA11992:Fast Matrix Operations(线段树)

题意: 有一个初始状态全为0的矩阵,一共有三个操作 1 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2)所有元素增加v 2 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2)所有元素设为v 3 x1 y1 x2 y2 v:查询子矩阵(x1,y1,x2,y2)的元素和,最大值和最小值 思路: 因为总元素葛素不超过10^6,而且更新是对于连续的行进行更新,所以我们可以把矩阵转化为一个一元组,通过下一行拼接在上一行的末尾,那么在更新与查询的时候只要对相应的区间进行操作即可 #in