uva 11992 为矩阵更新查询段树

http://uva.onlinejudge.org/index.php?

option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143

矩阵变成一行,然后计算位置。lrj给了线段树数组做法 可是我做的线段树空间过大,直接爆掉,所以换方法了

主要还是測试自己的线段树区间更新的模板

各种RE+WA之后AC,,,,。

做的时候出现的几个错误:

1、行和列弄错

2、build初始化的时候,mmin mmax 都初始化为0才对

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define lson(i) l , mid , (i)*2
#define rson(i) mid + 1 , r , ((i)*2 +1)
#define ll rt*2
#define rr (rt*2+1)

const int INFMIN = 0xffffffff;
const int INFMAX = 1000000009;//0x80000000;
const int MAXN = 30001000;
struct Node{
    int l,r;
    int mmax,mmin,sum,add,s;/*s去标记是不是被set*/
};
Node nodes[MAXN];

    int mmax,mmin,sum;
    void PushUp(int rt)
    {
        nodes[rt].mmax = max(nodes[ll].mmax,nodes[rr].mmax);
        nodes[rt].mmin = min(nodes[ll].mmin,nodes[rr].mmin);
        nodes[rt].sum = nodes[ll].sum + nodes[rr].sum;
    }
    void PushDown(int rt)
    {
        //if(nodes[rt].add && flag == 1)
        if(nodes[rt].add)
        {
            nodes[ll].add += nodes[rt].add;
            nodes[ll].mmin += nodes[rt].add;
            nodes[ll].mmax += nodes[rt].add;
            nodes[rr].add += nodes[rt].add;
            nodes[rr].mmin += nodes[rt].add;
            nodes[rr].mmax += nodes[rt].add;

            nodes[ll].sum += nodes[rt].add*(nodes[ll].r-nodes[ll].l+1);
            nodes[rr].sum += nodes[rt].add*(nodes[rr].r-nodes[rr].l+1);
            nodes[rt].add = 0;
        }
        //if(nodes[rt].s && flag == 2)
        if(nodes[rt].s)
        {
            nodes[ll].s = nodes[rr].s=nodes[rt].s;
            nodes[ll].mmin = nodes[ll].mmax = nodes[rr].mmax = nodes[rr].mmin = nodes[rt].mmax;
            nodes[ll].sum = nodes[rt].mmin*(nodes[ll].r-nodes[ll].l+1);
            nodes[rr].sum = nodes[rt].mmin*(nodes[rr].r-nodes[rr].l+1);
            nodes[ll].add = nodes[rr].add = 0;//////////////
            nodes[rt].s=0;
        }
    }
    void Build(int l,int r,int rt)
    {
        nodes[rt].l=l;
        nodes[rt].r=r;
        nodes[rt].add =0;
        nodes[rt].s=0;
        nodes[rt].sum =0;
        nodes[rt].mmin=0;
        nodes[rt].mmax=0;
        if(l == r)
        {
            //nodes[rt].mmin = nodes[rt].mmax = nodes[rt].sum =a[l];
            nodes[rt].mmin = nodes[rt].mmax = nodes[rt].sum =0;////////////////
            return ;
        }
        int mid = (nodes[rt].l+nodes[rt].r)/2;
        Build(lson(rt));
        Build(rson(rt));
        //PushUp(rt);
    }

    void Update(int l,int r,int add,int rt,int flag)
    {
/////////////////////////////////////////////////////////////////
//printf("rt=%d l=%d r=%d add=%d flag =%d nodes[rt].l=%d nodes[rt].r=%d\n",rt,l,r,add,flag,nodes[rt].l,nodes[rt].r);
        if(l<=nodes[rt].l && nodes[rt].r<=r)
        {
            if(flag == 1)/*increase*/
            {
                nodes[rt].mmax += add;
                nodes[rt].mmin += add;
                nodes[rt].add += add;
                nodes[rt].sum += add*(nodes[rt].r-nodes[rt].l+1);

            }
            else
            {
                nodes[rt].mmax = add;
                nodes[rt].mmin = add;
                nodes[rt].add=0;
                nodes[rt].s=1;
                nodes[rt].sum = add*(nodes[rt].r-nodes[rt].l+1);
            }
            return;
        }
        PushDown(rt);
        int mid = (nodes[rt].l+nodes[rt].r)/2;
        if(l<=mid)Update(l,r,add,ll,flag);
        if(r>mid)Update(l,r,add,rr,flag);
        PushUp(rt);
    }
    void Query(int l,int r,int rt)/*1表示mmin 2--mmax 3-sum*/
    {
    /////////////////////////////////////////////////////////////////
//printf("rt=%d l=%d r=%d  nodes[rt].l=%d nodes[rt].r=%d\n",rt,l,r,nodes[rt].l,nodes[rt].r);
 ///////////////////////////////////////////////////////////////////////////
        if(l<=nodes[rt].l && nodes[rt].r<=r)
        {
            mmin = min(mmin,nodes[rt].mmin);
            mmax = max(mmax,nodes[rt].mmax);
            sum += nodes[rt].sum;
            return ;
        }
        PushDown(rt);
        int mid = (nodes[rt].l+nodes[rt].r)/2;
        if(l<=mid)Query(l,r,ll);
        if(r>mid)Query(l,r,rr);
        PushUp(rt);
    }
    void clr()/*每次查询之前使用*/
    {
        sum =0;
        mmin=INFMAX;
        mmax=INFMIN;
    }

int main()
{
    //freopen("uva11992.txt","r",stdin);
    int r,c,m,v,flag,x1,y1,x2,y2;

    while(scanf("%d%d%d",&r,&c,&m)!=EOF)
    {
        Build(1,r*c,1);
        while(m--)
        {
            scanf("%d%d%d%d%d",&flag,&x1,&y1,&x2,&y2);
            if(flag<3)
            {
                scanf("%d",&v);
                for(int i=x1;i<=x2;i++)/*此处注意*/
                {
///////////////////////////////////////////////////////////////
//printf("i=%d\n",i);

                    Update(y1+(i-1)*c,y2+(i-1)*c,v,1,flag);
                }
            }
            else
            {
                int anssum=0,ansmin=INFMAX,ansmax=INFMIN;
                for(int i=x1;i<=x2;i++)
                {
                    clr();
                    Query(y1+(i-1)*c,y2+(i-1)*c,1);
                    ////////////////////////
                   // printf("**min=%d\n",mmin);
                    /////////////////
                    anssum+=sum;
                    ansmax=max(ansmax,mmax);
                    ansmin=min(ansmin,mmin);
                }
                printf("%d %d %d\n",anssum,ansmin,ansmax);
            }
        }
    }

    return 0;
}
时间: 2024-12-07 11:02:38

uva 11992 为矩阵更新查询段树的相关文章

【UVA】11992 - Fast Matrix Operations(段树模板)

主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小时的错. #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> using namespace

UVa 11992 Fast Matrix Operations(线段树双懒操作,二维转一维)

题意:给个r*c的矩形,三种操作,将一个子矩形权值+v,将一个子矩阵权值赋值为v,查询一个子矩阵sum,max,min.起初矩阵权值为0,保证r<=20,r*c<=1e6,操作次数不超过10000 链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697 题解:将二维转一维,设当前点为(x,y),则它在线段树上的点为(x-1)*c+y,由于行不超过20行,不妨枚举每一行,去操作.对于一维的线段树,要进行赋值,加法

uva 11992 线段树对矩阵进行更新查询

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143 把矩阵变成一行,然后计算位置,lrj给了线段树数组做法 但是我做的线段树空间过大,直接爆掉,所以换方法了 主要还是测试自己的线段树区间更新的模板 各种RE+WA之后AC,,,,, 做的时候出现的几个错误: 1.行和列弄错 2.build初始化的时候,mmin mmax 都初始化为0才对

hdu-4302-Holedox Eating-线段树-单点更新,有策略的单点查询

一開始实在是不知道怎么做,后来经过指导,猛然发现,仅仅须要记录某个区间内是否有值就可以. flag[i]:代表i区间内,共同拥有的蛋糕数量. 放置蛋糕的时候非常好操作,单点更新. ip:老鼠当前的位置 寻找吃哪一个蛋糕的时候: 1,要寻找0-ip这个区间内,位置最大的一个蛋糕的位置,记为ll. 2,要寻找ip-n这个区间内,位置最小的一个蛋糕的位置,记为rr. 找到ll,rr之后,就能够依据ll,rr跟ip的关系来确定该吃ll还是rr了. 怎样寻找ll呢? 假设在某个区间的右半边区间找到了一个数

zoj-1610-Count the Colors-线段树-区域更新,单点查询

线段树的区域更新,然后单点查询. x1 x2 c:区域更新x1-x2为c. 全部染色之后,从0-8000依次查询每个点的颜色.然后存贮每一种颜色有几块. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; #define lmin 0 #define rmax 8000 #

Wikioi 1082线段树成段更新成段查询

这题从昨晚搞到现在敲了又改好久,刚开始是update中错了,然后找到了.但是还错,然后因为题目没有数据的范围提示,所以弄了好久都不知道哪错了,最后看评论才知道是超int了,改了之后还有错,然后才发现虽然改成long long了,但是输出的时候没改,哈哈-- #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque> #in

hdu-1698-Just a Hook-线段树-区域更新,区域查询

flag[i]:标记i这个区间的值. val[i]:i这个区间的长度 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; #define INF 99999999 #define lmin 1 #define rmax n #define lson l,(l+r)/2,rt

段树 基于单点更新 敌人阵容

称号:敌人阵容 标准段树模板代码: #include<cstdio> #include<cstring> const int maxn = 500000 + 10; struct Node{ int left, right, count; }node[maxn]; int a[maxn]; /*********************************** ***************建树**************** ************i是区间序号********

HDU-5172-GTY&#39;s gay friends-线段树单点更新

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172 题意:给出n个数,m个询问,问你[l,r]区间内是否为1到r-l+1的全排列. 大小很容易我们通过记录前缀和很容易求出来,但是关键是去重. 考虑线段树做法,我们记录每个点的靠左最近的相同元素的位置,然后求 整个区间的最大值(即最大的前驱)如果小于l,即满足条件,输出YES. 好吧,其实这个题目我是搜的RMQ算法出来的,因为我想练一下RMQ算法,所以我就看了一下别人的博客,自己也写了一下,结果死