zoukankan      html  css  js  c++  java
  • 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
    ",ressum,resmin,resmax);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    MicroPython实例之TurnipBit开发板自动浇水实验
    MicropPython的学习,如何从0到1?
    MicroPython最全资料免费获取
    MicroPython技术及应用前景
    如何将AD原理图直接转为Orcad原理图
    USB音频声卡的时钟同步方式----同步、异步、自适应
    字符串指针数组长度
    关于传统模拟电话按键时间
    小米笔记本13.3寸 八代i5独显 记录
    小米笔记本Air 13.3 熄屏 大概率无法唤醒问题(已解决)
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5735097.html
Copyright © 2011-2022 走看看