首页 > 其他 > 详细

UVA 11992 Fast Matrix Operations (二维线段树)

时间:2014-02-23 13:02:22      阅读:351      评论:0      收藏:0      [点我收藏+]

解法:因为至多20行,所以至多建20棵线段树,每行建一个。具体实现如下,有些复杂,慢慢看吧。

bubuko.com,布布扣
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 1000010

struct node
{
    int mini,maxi,sum;
    int addmark,setmark;
}tree[21][4*N];

int i;

void pushup(int i,int rt)
{
    tree[i][rt].sum = tree[i][2*rt].sum + tree[i][2*rt+1].sum;
    tree[i][rt].mini = min(tree[i][2*rt].mini,tree[i][2*rt+1].mini);
    tree[i][rt].maxi = max(tree[i][2*rt].maxi,tree[i][2*rt+1].maxi);
}

void build(int i,int l,int r,int rt)
{
    tree[i][rt].sum = tree[i][rt].mini = tree[i][rt].maxi = 0;
    tree[i][rt].setmark = -1;
    tree[i][rt].addmark = 0;
    if(l == r)
        return;
    int mid = (l+r)/2;
    build(i,l,mid,2*rt);
    build(i,mid+1,r,2*rt+1);
    pushup(i,rt);
}

void pushdown(int i,int l,int r,int rt)
{
    if(tree[i][rt].setmark == -1 && tree[i][rt].addmark == 0)
        return;
    int mid = (l+r)/2;
    if(tree[i][rt].setmark >= 0)
    {
        tree[i][2*rt].sum = tree[i][rt].setmark*(mid-l+1);
        tree[i][2*rt+1].sum = tree[i][rt].setmark*(r-mid);
        tree[i][2*rt].mini = tree[i][2*rt+1].mini = tree[i][rt].setmark;  // 
        tree[i][2*rt].maxi = tree[i][2*rt+1].maxi = tree[i][rt].setmark;  //
        tree[i][2*rt].addmark = tree[i][2*rt+1].addmark = 0;  //
        tree[i][2*rt].setmark = tree[i][2*rt+1].setmark = tree[i][rt].setmark;
        tree[i][rt].setmark = -1;
    }
    if(tree[i][rt].addmark > 0)
    {
        tree[i][2*rt].sum += tree[i][rt].addmark*(mid-l+1);
        tree[i][2*rt+1].sum += tree[i][rt].addmark*(r-mid);
        tree[i][2*rt].maxi += tree[i][rt].addmark;  //
        tree[i][2*rt].mini += tree[i][rt].addmark;
        tree[i][2*rt+1].maxi += tree[i][rt].addmark;
        tree[i][2*rt+1].mini += tree[i][rt].addmark;  //
        tree[i][2*rt].addmark += tree[i][rt].addmark;
        tree[i][2*rt+1].addmark += tree[i][rt].addmark;
        tree[i][rt].addmark = 0;
    }
}

void add(int l,int r,int aa,int bb,int val,int rt)
{
    if(aa>r||bb<l)
        return;
    if(aa<=l&&bb>=r)
    {
        tree[i][rt].addmark += val;
        //tree[i][rt].setmark = -1;
        tree[i][rt].sum += (r-l+1)*val;
        tree[i][rt].maxi += val;
        tree[i][rt].mini += val;
        return;
    }
    pushdown(i,l,r,rt);
    int mid = (l+r)/2;
    if(aa<=mid)
        add(l,mid,aa,bb,val,2*rt);
    if(bb>mid)
        add(mid+1,r,aa,bb,val,2*rt+1);
    pushup(i,rt);
}

void setval(int l,int r,int aa,int bb,int val,int rt)
{
    if(aa>r||bb<l)
        return;
    if(aa<=l&&bb>=r)
    {
        tree[i][rt].setmark = val;
        tree[i][rt].addmark = 0;
        tree[i][rt].sum = val*(r-l+1);
        tree[i][rt].maxi = tree[i][rt].mini = val;
        return;
    }
    pushdown(i,l,r,rt);
    int mid = (l+r)/2;
    if(aa<=mid)
        setval(l,mid,aa,bb,val,2*rt);
    if(bb>mid)
        setval(mid+1,r,aa,bb,val,2*rt+1);
    pushup(i,rt);
}

struct node_ans
{
    int sum;
    int mini,maxi;
};

node_ans query(int l,int r,int aa,int bb,int rt)
{
    node_ans res,ka1,ka2;
    if(aa<=l && bb>=r)
    {
        res.sum = tree[i][rt].sum;
        res.maxi = tree[i][rt].maxi;
        res.mini = tree[i][rt].mini;
        return res;
    }
    pushdown(i,l,r,rt);
    int mid = (l+r)/2;
    if(bb<=mid)
        return query(l,mid,aa,bb,2*rt);
    else if(aa>mid)
        return query(mid+1,r,aa,bb,2*rt+1);
    else
    {
        ka1 = query(l,mid,aa,bb,2*rt);
        ka2 = query(mid+1,r,aa,bb,2*rt+1);
        res.sum = ka1.sum + ka2.sum;
        res.maxi = max(ka1.maxi,ka2.maxi);
        res.mini = min(ka1.mini,ka2.mini);
        return res;
    }
}

int main()
{
    int r,c,m;
    int k,zuo;
    int x1,y1,x2,y2,val;
    int sum,mmax,mmin;
    while(scanf("%d%d%d",&r,&c,&m)!=EOF)
    {
        for(i=1;i<=r;i++)
        {
            build(i,1,c,1);
        }
        for(k=0;k<m;k++)
        {
            scanf("%d",&zuo);
            if(zuo == 1)
            {
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
                for(i=x1;i<=x2;i++)
                {
                    add(1,c,y1,y2,val,1);
                }
            }
            else if(zuo == 2)
            {
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
                for(i=x1;i<=x2;i++)
                {
                    setval(1,c,y1,y2,val,1);
                }
            }
            else 
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                node_ans la;
                sum = 0;
                mmax = -Mod;
                mmin = Mod;
                for(i=x1;i<=x2;i++)
                {
                    la = query(1,c,y1,y2,1);
                    sum += la.sum;
                    mmax = max(mmax,la.maxi);
                    mmin = min(mmin,la.mini);
                }
                printf("%d %d %d\n",sum,mmin,mmax);
            }
        }
    }
}
View Code

UVA 11992 Fast Matrix Operations (二维线段树)

原文:http://www.cnblogs.com/whatbeg/p/3561449.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!