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 of operations:

1 x1 y1 x2 y2 v Increment each element (x, y) in submatrix (x1, y1, x2, y2) by v (v > 0)

2 x1 y1 x2 y2 v Set each element (x, y) in submatrix (x1, y1, x2, y2) to v

3 x1 y1 x2 y2 Output the summation, min value and max value of submatrix (x1, y1, x2, y2)

In the above descriptions, submatrix (x1, y1, x2, y2) means all the elements (x, y) satisfying x1 ≤ x ≤ x2 and y1 ≤ x ≤ y2. It is guaranteed that 1 ≤ x1 ≤ x2 ≤ r, 1 ≤ y1 ≤ y2 ≤ c. After any operation, the sum of all the elements in the matrix does not exceed 109 .

Input

There are several test cases. The first line of each case contains three positive integers r, c, m, where m (1 ≤ m ≤ 20, 000) is the number of operations. Each of the next m lines contains a query. There will be at most twenty rows in the matrix. The input is terminated by end-of-file (EOF).

Output

For each type-3 query, print the summation, min and max.

Sample Input

4 4 8

1 1 2 4 4 5

3 2 1 4 4

1 1 1 3 4 2

3 1 2 4 4

3 1 1 3 4

2 2 1 4 4 2

3 1 2 4 4

1 1 1 4 3 3

Sample Output

45 0 5

78 5 7

69 2 7

39 2 7

题意:给你一个矩阵,有三个操作。首先很容易想到用线段树来做,注意到r<=20,故可以开20个线段树来储存每一行的信息。

然后有两个标记,set和add,在push_down的时候,先处理set,后处理add。还有需要注意的是,在更新时,如果是set操作,会将add置为0,而add则不改变set。

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1e6+100;
const int INF = 0x3f3f3f3f;
struct Node
{
    int l,r;
    int sum,mi,ma;
    int addv,setv;
}segTree[22][MAXN*4];
void push_up(int idx,int id)
{
    segTree[idx][id].sum=segTree[idx][id*2].sum+segTree[idx][id*2+1].sum;
    segTree[idx][id].mi=min(segTree[idx][id*2].mi,segTree[idx][id*2+1].mi);
    segTree[idx][id].ma=max(segTree[idx][id*2].ma,segTree[idx][id*2+1].ma);
}
void push_down(int idx,int id)
{
    int mid=(segTree[idx][id].l+segTree[idx][id].r)/2;
    if(segTree[idx][id].setv>=0)
    {
        segTree[idx][id*2].setv=segTree[idx][id*2+1].setv=segTree[idx][id].setv;
        segTree[idx][id*2].addv=segTree[idx][id*2+1].addv=0;
        segTree[idx][id*2].sum=(mid-segTree[idx][id].l+1)*segTree[idx][id].setv;
        segTree[idx][id*2+1].sum=(segTree[idx][id].r-mid)*segTree[idx][id].setv;
        segTree[idx][id*2].mi=segTree[idx][id*2].ma=segTree[idx][id].setv;
        segTree[idx][id*2+1].mi=segTree[idx][id*2+1].ma=segTree[idx][id].setv;
        segTree[idx][id].setv=-1;
    }
    if(segTree[idx][id].addv>0)
    {
        segTree[idx][id*2].addv+=segTree[idx][id].addv;
        segTree[idx][id*2+1].addv+=segTree[idx][id].addv;
        segTree[idx][id*2].sum+=(mid-segTree[idx][id].l+1)*segTree[idx][id].addv;
        segTree[idx][id*2+1].sum+=(segTree[idx][id].r-mid)*segTree[idx][id].addv;
        segTree[idx][id*2].mi+=segTree[idx][id].addv;
        segTree[idx][id*2].ma+=segTree[idx][id].addv;
        segTree[idx][id*2+1].mi+=segTree[idx][id].addv;
        segTree[idx][id*2+1].ma+=segTree[idx][id].addv;
        segTree[idx][id].addv=0;
    }
}
void build(int idx,int id,int l,int r)
{
    segTree[idx][id].l=l;
    segTree[idx][id].r=r;
    if(l==r)
    {
        segTree[idx][id].sum=0;
        segTree[idx][id].mi=0;
        segTree[idx][id].ma=0;
        segTree[idx][id].addv=0;
        segTree[idx][id].setv=-1;
        return;
    }
    int mid=(l+r)/2;
    build(idx,id*2,l,mid);
    build(idx,id*2+1,mid+1,r);
    push_up(idx,id);
}
void update(int idx,int id,int l,int r,int op,int val)
{
    if(segTree[idx][id].l>=l&&segTree[idx][id].r<=r)
    {
        if(op==1)
        {
            segTree[idx][id].addv+=val;
            segTree[idx][id].sum+=val*(segTree[idx][id].r-segTree[idx][id].l+1);
            segTree[idx][id].mi+=val;
            segTree[idx][id].ma+=val;
        }
        else
        {
            segTree[idx][id].addv=0;
            segTree[idx][id].setv=val;
            segTree[idx][id].sum=val*(segTree[idx][id].r-segTree[idx][id].l+1);
            segTree[idx][id].mi=val;
            segTree[idx][id].ma=val;
        }
        return;
    }
    push_down(idx,id);
    int mid=(segTree[idx][id].l+segTree[idx][id].r)/2;
    if(l>mid) update(idx,id*2+1,l,r,op,val);
    else if(r<=mid) update(idx,id*2,l,r,op,val);
    else
    {
        update(idx,id*2,l,mid,op,val);
        update(idx,id*2+1,mid+1,r,op,val);
    }
    push_up(idx,id);
}
int querysum(int idx,int id,int l,int r)
{
    int res=0;
    if(segTree[idx][id].l>=l&&segTree[idx][id].r<=r) return segTree[idx][id].sum;
    push_down(idx,id);
    int mid=(segTree[idx][id].l+segTree[idx][id].r)/2;
    if(l>mid) res+=querysum(idx,id*2+1,l,r);
    else if(r<=mid) res+=querysum(idx,id*2,l,r);
    else
    {
        res+=querysum(idx,id*2,l,mid);
        res+=querysum(idx,id*2+1,mid+1,r);
    }
    push_up(idx,id);
    return res;
}
int querymax(int idx,int id,int l,int r)
{
    int res=-INF;
    if(segTree[idx][id].l>=l&&segTree[idx][id].r<=r) return segTree[idx][id].ma;
    push_down(idx,id);
    int mid=(segTree[idx][id].l+segTree[idx][id].r)/2;
    if(l>mid) res=max(res,querymax(idx,id*2+1,l,r));
    else if(r<=mid) res=max(res,querymax(idx,id*2,l,r));
    else
    {
        res=max(res,querymax(idx,id*2,l,mid));
        res=max(res,querymax(idx,id*2+1,mid+1,r));
    }
    push_up(idx,id);
    return res;
}
int querymin(int idx,int id,int l,int r)
{
    int res=INF;
    if(segTree[idx][id].l>=l&&segTree[idx][id].r<=r) return segTree[idx][id].mi;
    push_down(idx,id);
    int mid=(segTree[idx][id].l+segTree[idx][id].r)/2;
    if(l>mid) res=min(res,querymin(idx,id*2+1,l,r));
    else if(r<=mid) res=min(res,querymin(idx,id*2,l,r));
    else
    {
        res=min(res,querymin(idx,id*2,l,mid));
        res=min(res,querymin(idx,id*2+1,mid+1,r));
    }
    push_up(idx,id);
    return res;
}
int main()
{
    int r,c,m,op;
    int x1,y1,x2,y2,val;
    while(scanf("%d%d%d",&r,&c,&m)!=EOF)
    {
        for(int i=1;i<=r;i++) build(i,1,1,c);
        while(m--)
        {
            scanf("%d",&op);
            if(op<3)
            {
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
                for(int i=x1;i<=x2;i++) update(i,1,y1,y2,op,val);
            }
            else
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                int ressum=0,resmax=-INF,resmin=INF;
                for(int i=x1;i<=x2;i++)
                {
                    ressum+=querysum(i,1,y1,y2);
                    resmax=max(resmax,querymax(i,1,y1,y2));
                    resmin=min(resmin,querymin(i,1,y1,y2));
                }
                printf("%d %d %d\n",ressum,resmin,resmax);
            }
        }
    }
    return 0;
}
时间: 2024-10-12 02:54:19

UVa 11992 Fast Matrix Operations (线段树)的相关文章

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

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行,不妨枚举每一行,去操作.对于一维的线段树,要进行赋值,加法

线段树(多维+双成段更新) 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 =

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.然后修改查询

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(线段树)

题意: 有一个初始状态全为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

UVA11992 - Fast Matrix Operations(段树部分的变化)

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行,所以能够将这个矩阵的元素构建一