zoukankan      html  css  js  c++  java
  • UVA

    UVA - 11992

    题意:有一个 r*c 的全 0矩阵, 进行 3 种操作。
    1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素加val;
    2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素变为val;
    3 x1 y1 x2 y2 val 表示输出(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素的和,最小值和最大值。
    共有m次操作(1<=m<=20000) 。  矩阵不超过20 行,元素总数不超过 1e6 。

    tags:因为不超过 20行,所以我们每行建棵线段树,然后就是基本的区间更新查询。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    #define mid  (l+(r-l)/2)
    #define  PIII  pair<ll, pair< ll, ll >  >
    typedef long long ll;
    const int N = 1000005;
    
    struct Item {
        ll  sum, minn, maxn, addv, setv;
    } ;
    vector< Item > tr[21];
    int n, m, q;
    void Init() {
        rep(i,1,n) tr[i].clear();
        rep(i,1,n) rep(j,1,m<<2)
            tr[i].PB(Item());
    }
    void pushdown(int ii, int ro, int l, int r)
    {
        if(tr[ii][ro].setv) {
            tr[ii][ro<<1].addv = tr[ii][ro<<1|1].addv = 0;
            tr[ii][ro<<1].setv = tr[ii][ro<<1|1].setv = tr[ii][ro].setv;
            tr[ii][ro<<1].sum = tr[ii][ro].setv*(mid-l+1);
            tr[ii][ro<<1|1].sum = tr[ii][ro].setv*(r-mid);
            tr[ii][ro<<1].maxn = tr[ii][ro<<1].minn = tr[ii][ro].setv;
            tr[ii][ro<<1|1].maxn = tr[ii][ro<<1|1].minn = tr[ii][ro].setv;
        }
        tr[ii][ro<<1].addv += tr[ii][ro].addv;
        tr[ii][ro<<1|1].addv += tr[ii][ro].addv;
        tr[ii][ro<<1].sum += tr[ii][ro].addv*(mid-l+1);
        tr[ii][ro<<1|1].sum += tr[ii][ro].addv*(r-mid);
        tr[ii][ro<<1].maxn += tr[ii][ro].addv;
        tr[ii][ro<<1].minn += tr[ii][ro].addv;
        tr[ii][ro<<1|1].maxn += tr[ii][ro].addv;
        tr[ii][ro<<1|1].minn += tr[ii][ro].addv;
        tr[ii][ro].addv = tr[ii][ro].setv = 0;
    }
    void pushup(int ii, int ro)
    {
        tr[ii][ro].maxn = max(tr[ii][ro<<1].maxn, tr[ii][ro<<1|1].maxn);
        tr[ii][ro].minn = min(tr[ii][ro<<1].minn, tr[ii][ro<<1|1].minn);
        tr[ii][ro].sum = tr[ii][ro<<1].sum + tr[ii][ro<<1|1].sum;
    }
    void update(int ii, int ro, int l, int r, int ql, int qr, int flag, int vi)
    {
        if(ql<=l && r<=qr) {
            if(flag==1) {
                tr[ii][ro].addv += vi;
                tr[ii][ro].sum += 1LL*vi*(r-l+1);
                tr[ii][ro].maxn += vi;
                tr[ii][ro].minn += vi;
            } else {
                tr[ii][ro].setv = vi;
                tr[ii][ro].addv = 0;
                tr[ii][ro].sum = 1LL*vi*(r-l+1);
                tr[ii][ro].maxn = tr[ii][ro].minn = vi;
            }
            return ;
        }
        pushdown(ii, ro, l, r);
        if(mid<qr) update(ii, ro<<1|1, mid+1, r, ql, qr, flag, vi);
        if(ql<=mid) update(ii, ro<<1, l, mid, ql, qr, flag, vi);
        pushup(ii, ro);
    }
    PIII get_ans(PIII x, PIII y) {
        PIII  ret;
        ret.fi = x.fi+y.fi;
        ret.se.fi = max(x.se.fi, y.se.fi);
        ret.se.se = min(x.se.se, y.se.se);
        return ret;
    }
    PIII query(int ii, int ro, int l, int r, int ql, int qr)
    {
        if(ql<=l && r<=qr) {
            return MP(tr[ii][ro].sum, MP(tr[ii][ro].maxn, tr[ii][ro].minn));
        }
        pushdown(ii, ro, l, r);
        PIII ret = MP(0, MP(0,1e18));
        if(mid<qr) ret = get_ans(ret, query(ii, ro<<1|1, mid+1, r, ql, qr));
        if(ql<=mid) ret = get_ans(ret, query(ii, ro<<1, l, mid, ql, qr));
        pushup(ii, ro);
        return ret;
    }
    int main()
    {
        while(~scanf("%d%d%d", &n, &m, &q))
        {
            Init();
            int ti, x1, y1, x2, y2, vi;
            while(q--)
            {
                scanf("%d", &ti);
                if(ti==1) {
                    scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &vi);
                    rep(i,x1,x2) update(i, 1, 1, m, y1, y2, 1, vi);
                }
                else if(ti==2) {
                    scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &vi);
                    rep(i,x1,x2) update(i, 1, 1, m, y1, y2, 2, vi);
                }
                else {
                    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                    PIII  ans = MP(0, MP(0,1e18));
                    rep(i,x1,x2) ans = get_ans(ans, query(i, 1, 1, m, y1, y2));
                    printf("%lld %lld %lld
    ", ans.fi, ans.se.se, ans.se.fi);
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    UIFont的使用和字体类型总结
    LOJ-10100(割点个数)
    LOJ-10099(点双联通)
    poj-3177(并查集+双联通分量+Tarjan算法)
    图论:割点和桥
    牛客训练五:炫酷数学(思维)
    牛客训练五:炫酷路途(c++与dp)
    并查集的两种实现(按秩合并+路径压缩)
    牛客训练六:海啸(二维树状数组+vector函数的使用)
    牛客训练六:美食(贪心)
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8453900.html
Copyright © 2011-2022 走看看