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;
    }
  • 相关阅读:
    SQL Server AUTO_FIX_Login_Users
    SQL Server Always On 切换主机Login和User无法匹配解决方案
    SQL Server 目标主体名称不正确,无法生成 SSPI 上下文
    SQL Server Rebuild Index
    jqery和js如何判断checkbox是否选中 (转)
    jxl
    jxl 管理excel
    Bootstrap库之Modals
    jquery attr()
    js 验证数字(验证字符串是否是数字)
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5735097.html
Copyright © 2011-2022 走看看