码迷,mamicode.com
首页 > 其他好文 > 详细

UVA - 11992 线段树

时间:2018-02-19 16:39:43      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:scan   first   oid   ace   using   space   printf   pac   add   

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\n", ans.fi, ans.se.se, ans.se.fi);
            }
        }
    }

    return 0;
}

UVA - 11992 线段树

标签:scan   first   oid   ace   using   space   printf   pac   add   

原文地址:https://www.cnblogs.com/sbfhy/p/8453900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!