UVA 11992 Fast Matrix Operations (降维)

题意:对一个矩阵进行子矩阵操作。

元素对多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作。

一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测没有),如果判断一下然后建树复杂度是min(RlogC,ClogR)。

代码中结点没有保存l和r,而且询问是保存在全局变量中,这样做比较省空间。但是也有缺点,比如推区间结点数量的时候会麻烦一点。

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

const int maxn = 1e6+1;
int R,C;

#define lid (id<<1)
#define rid (id<<1|1)
struct Seg
{
    int add,setv;
    int Max,Min,sum;
}tr[maxn<<2];

#define OP1(id,val)\
tr[id].add += val; tr[id].Max += val; tr[id].Min += val; tr[id].sum += (r-l+1)*val;
#define OP2(id,val)\
tr[id].Max = tr[id].setv = tr[id].Min = val; tr[id].add = 0; tr[id].sum = val*(r-l+1);

inline void push_down(int id,int l,int r)
{
    int lc = lid, rc = rid, mid = (l+r)>>1;
    if(tr[id].setv>=0){
        int &t = tr[id].setv;
        swap(r,mid);
        OP2(lc,t);
        swap(l,r); l++; swap(mid,r);
        OP2(rc,t);
       // l--; swap(mid,l);
        t = -1;
    }
    if(tr[id].add>0){
        int &t = tr[id].add;
        swap(r,mid);
        OP1(lc,t);
        swap(l,r); l++; swap(mid,r);
        OP1(rc,t);
       // l--; swap(mid,l);
        t = 0;
    }
}

inline void maintain(int id)
{
    int lc = lid, rc = rid;
    tr[id].sum = tr[lc].sum + tr[rc].sum;
    tr[id].Max = max(tr[lc].Max,tr[rc].Max);
    tr[id].Min = min(tr[lc].Min,tr[rc].Min);
}

int ql,qr,val;
void add1D(int l = 0,int r = R*C-1,int id = 1)
{
    if(ql<=l&&r<=qr) { OP1(id,val) return; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    push_down(id,l,r);
    if(ql<=mid) add1D(l,mid,lc);
    if(qr>mid) add1D(mid+1,r,rc);
    maintain(id);
}

void set1D(int l = 0,int r = R*C-1,int id = 1)
{
    if(ql<=l&&r<=qr) { OP2(id,val) return; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    push_down(id,l,r);
    if(ql<=mid) set1D(l,mid,lc);
    if(qr>mid) set1D(mid+1,r,rc);
    maintain(id);
}

int queryMax1D(int l = 0,int r = R*C-1,int id = 1)
{
    if(ql<=l&&r<=qr) { return tr[id].Max; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    push_down(id,l,r);
    int ret = 0;
    if(ql<=mid) ret = max(ret,queryMax1D(l,mid,lc));
    if(qr>mid) ret = max(ret,queryMax1D(mid+1,r,rc));
    return ret;
}

const int INF = 0x3f3f3f3f;

int queryMin1D(int l = 0,int r = R*C-1,int id = 1)
{
    if(ql<=l&&r<=qr) { return tr[id].Min; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    push_down(id,l,r);
    int ret = INF;
    if(ql<=mid) ret = min(ret,queryMin1D(l,mid,lc));
    if(qr>mid) ret = min(ret,queryMin1D(mid+1,r,rc));
    return ret;
}

int querySum1D(int l = 0,int r = R*C-1,int id = 1)
{
    if(ql<=l&&r<=qr) { return tr[id].sum; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    push_down(id,l,r);
    int ret = 0;
    if(ql<=mid) ret += querySum1D(l,mid,lc);
    if(qr>mid) ret += querySum1D(mid+1,r,rc);
    return ret;
}

//[0,r)
void add2D(int x1,int y1,int x2,int y2,int v)
{
    val = v;
    int st = x1*C+y1, len = y2-y1;
    for(int x = x1; x <= x2; x++){
        ql = st; qr = st+len;
        add1D();
        st += C;
    }
}

void set2D(int x1,int y1,int x2,int y2,int v)
{
    val = v;
    int st = x1*C+y1, len = y2-y1;
    for(int x = x1; x <= x2; x++){
        ql = st; qr = st+len;
        set1D();
        st += C;
    }
}

int querySum2D(int x1,int y1,int x2,int y2)
{
    int ret = 0;
    int st = x1*C+y1, len = y2-y1;
    for(int x = x1; x <= x2; x++){
        ql = st; qr = st+len;
        ret += querySum1D();
        st += C;
    }
    return ret;
}

int queryMax2D(int x1,int y1,int x2,int y2)
{
    int ret = 0;
    int st = x1*C+y1, len = y2-y1;
    for(int x = x1; x <= x2; x++){
        ql = st; qr = st+len;
        ret = max(ret,queryMax1D());
        st += C;
    }
    return ret;
}

int queryMin2D(int x1,int y1,int x2,int y2)
{
    int ret = INF;
    int st = x1*C+y1, len = y2-y1;
    for(int x = x1; x <= x2; x++){
        ql = st; qr = st+len;
        ret = min(ret,queryMin1D());
        st += C;
    }
    return ret;
}

void

int main()
{
    //freopen("in.txt","r",stdin);
    int m;
    while(~scanf("%d%d%d",&R,&C,&m)){
        ql = 0; qr = R*C-1; val = 0;
        set1D();
        while(m--){
            int op ,x1 ,y1 ,x2 ,y2 ; scanf("%d%d%d%d%d",&op,&x1,&y1,&x2,&y2);
            if(op == 1){
                int v ; scanf("%d",&v);
                add2D(x1-1,y1-1,x2-1,y2-1,v);
            }else if(op == 2){
                int v ; scanf("%d",&v);
                set2D(x1-1,y1-1,x2-1,y2-1,v);
            }else {
                x1--;x2--;y1--;y2--;
                printf("%d %d %d\n",querySum2D(x1,y1,x2,y2),queryMin2D(x1,y1,x2,y2),queryMax2D(x1,y1,x2,y2));
            }
        }
    }
    return 0;
}
时间: 2024-10-26 20:43:51

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

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(线段树双懒操作,二维转一维)

题意:给个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 =

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

基本的线段树,需要注意的是由于有set和add操作,懒惰标记下推的时候,优先递推set,之后递推add,每次执行set操作将add标记清0 WA了好几次是因为计算那一段的时候出问题了,可笑的是我对着模板找了一个多小时的错. #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> using na

【UVA】11992 - Fast Matrix Operations(段树模板)

主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小时的错. #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> using namespace

uva 1401 Fast Matrix Operations 快速矩阵操作 (线段树 区间修改和查询)

题意:给一个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 x2 y2   查询子矩阵(x1 y1 x2 y2)的元素和.最小值.最大值. 子矩阵(x1 y1 x2 y2)是指满足 x1 <= x <= x2, y1 <= y <= y2的所有元素(x,y). 矩阵不超过20行,矩阵总元素可多达10^6个. 思路

Fast Matrix Operations(UVA)11992

UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素add上val: 2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素set为val: 3 x1 y1 x2 y2 val 表示输