UVA 11992 Fast Matrix Operations 线段树

原创 2015年11月20日 01:19:50

大致题意:给你一个r*c的矩阵,r*c<=1e6,给你三种操作,第一种,1 x1 y1 x2 y2 u ,把[x1,y1,x2,y2]子矩阵所有的元素都加上u,第二种,2 x1 y1 x2 y2 u,把[x1,y1,x2,y2]子矩阵的所有元素变成u,第三种,3 x1 y1 x2 y2,查询[x1,y1,x2,y2]所有元素的和,最大值,最小值。

思路:开始并不知道怎么搞,直到发现了r<=20之后,直接暴力好了,反正一个查询或更新的复杂度也就20*log(N)

坑点:是我没想好,第二种操作会对第一种操作有影响,具体就是第二种操作的时候会抵消第一种操作之前所做的状态。所以要处理一下。

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697

#include <cstdio>
#include <cmath>
#include <iostream>

#define change(x,y) (x-1)*clo+y
#define dist(rt) (t[rt].y - t[rt].x + 1)

using namespace std;

const int MAXN = 1e6+5;

struct Node {
    int x,y;
    int add,live; //add代表这个区间加上的值,live表示把这个区间所有值变成live;
    int minnum,maxnum; //minnum 区间最小,区间最大;
    int sum; //区间内总和;
}t[MAXN<<2];

int n,m;
int row,clo;

void Push_Up(int rt) {
    t[rt].sum = t[rt<<1].sum + t[rt<<1|1].sum;
    t[rt].maxnum = max(t[rt<<1].maxnum,t[rt<<1|1].maxnum);
    t[rt].minnum = min(t[rt<<1].minnum,t[rt<<1|1].minnum);
}

void Push_Down(int rt) {
    if(t[rt].live) {
        t[rt<<1].sum = dist(rt<<1) * t[rt].live;
        t[rt<<1|1].sum = dist(rt<<1|1) * t[rt].live;
        t[rt<<1].maxnum = t[rt].live; t[rt<<1|1].maxnum = t[rt].live;
        t[rt<<1].minnum = t[rt].live; t[rt<<1|1].minnum = t[rt].live;
        t[rt<<1].live = t[rt<<1|1].live = t[rt].live;
        t[rt<<1].add  = t[rt<<1|1].add  = 0;//去掉live 对 add的影响,之前add的要全部取消掉
        t[rt].live = 0;
    }
    if(t[rt].add) {
        t[rt<<1].sum += dist(rt<<1) * t[rt].add;
        t[rt<<1|1].sum += dist(rt<<1|1) * t[rt].add;
        t[rt<<1].maxnum += t[rt].add; t[rt<<1|1].maxnum += t[rt].add;
        t[rt<<1].minnum += t[rt].add; t[rt<<1|1].minnum += t[rt].add;
        t[rt<<1].add += t[rt].add; t[rt<<1|1].add += t[rt].add;
        t[rt].add = 0;
    }

}

void Build(int x,int y,int rt) {
    t[rt].x = x; t[rt].y = y;
    t[rt].add = t[rt].live = 0;
    if(x == y) {
        t[rt].sum = 0;
        t[rt].maxnum = 0;
        t[rt].minnum = 0;
        return ;
    }
    int mid = (x + y) >> 1;
    Build(x,mid,rt<<1);
    Build(mid+1,y,rt<<1|1);
    Push_Up(rt);
}

void Update(int rt,int left,int right,int u,int flag) {
    if(t[rt].x >= left && t[rt].y <= right) {
        if(flag) {
            t[rt].sum += dist(rt) * u;
            t[rt].add += u;
            t[rt].maxnum += u;
            t[rt].minnum += u;
        }
        else {
            t[rt].sum = dist(rt) * u;
            t[rt].live = u;
            t[rt].add = 0;//去掉live 对 add的影响,之前add的要全部取消掉
            t[rt].maxnum = u;
            t[rt].minnum = u;
        }
        return ;
    }
    int mid = (t[rt].x + t[rt].y) >> 1;
    Push_Down(rt);
    if(mid >= left) Update(rt<<1,left,right,u,flag);
    if(mid < right) Update(rt<<1|1,left,right,u,flag);
    Push_Up(rt);
}

int sum ;
int maxnum , minnum;

void Query(int rt,int left,int right) {
    if(t[rt].x >= left && t[rt].y <= right) {
        sum += t[rt].sum;
        maxnum = max(maxnum,t[rt].maxnum);
        minnum = min(minnum,t[rt].minnum);
        return ;
    }
    int mid = (t[rt].x + t[rt].y) >> 1;
    Push_Down(rt);
    if(mid >= left) Query(rt<<1,left,right);
    if(mid < right) Query(rt<<1|1,left,right);
    Push_Up(rt);
}

void Print_Tree(int rt) {
    static int cnt = 0;
    Push_Down(rt);
    if(t[rt].x == t[rt].y) {
        cnt ++;
        if(cnt % 4 == 0) {
            printf("%d\n",t[rt].sum);
        }
        else {
            printf("%d ",t[rt].sum);
        }
        return ;
    }
    Print_Tree(rt<<1);
    Print_Tree(rt<<1|1);
}

void input() {
    Build(1,change(row,clo),1);
    int ok,u;
    int x1,y1,x2,y2;
    for(int i = 1 ; i <= n ; i ++) {
        //Print_Tree(1);
        scanf("%d %d %d %d %d",&ok,&x1,&y1,&x2,&y2);
        if(ok == 1) {
            scanf("%d",&u); //add 
            for(int j = x1 ; j <= x2 ; j ++) {
                Update(1,change(j,y1),change(j,y2),u,1);
            }
        }
        else if(ok == 2) { //live
            scanf("%d",&u);
            for(int j = x1 ; j <= x2 ; j ++) {
                Update(1,change(j,y1),change(j,y2),u,0);
            }
        }
        else {
            sum = 0;
            minnum = 0x3f3f3f3f;
            maxnum = 0;
            for(int j = x1 ; j <= x2 ; j ++) {
                Query(1,change(j,y1),change(j,y2));
            }
            printf("%d %d %d\n",sum,minnum,maxnum);
        }
    }
}

void solve() {

}

int main(void) {
    //freopen("a.in","r",stdin);
    while(~scanf("%d %d %d",&row,&clo,&n)) {
        input();
        solve();
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

UVA11992:Fast Matrix Operations(线段树)

题意: 有一个初始状态全为0的矩阵,一共有三个操作 1 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2)所有元素增加v 2 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2...

uva 11992 Fast Matrix Operations (线段树区间更新)

题意: 给你一个矩阵,然后有3种操作: 1 x1 y1 x2 y2 val 是将矩阵x1 y1 x2 y2的区间内的值全部增加val 2 x1 y1 x2 y2 val 是将矩阵x1 ...

uva11992 Fast Matrix Operations (线段树)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18697 题意:给定N*M的矩阵,初始值为0。有三种操作①将x1~x2行...
  • w20810
  • w20810
  • 2015年07月13日 13:53
  • 249

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

Fast Matrix Operations 题意: 给定一个r  op1: 子矩阵元素全部增加v  op2: 子矩阵元素全部变成v  op3: 查询子矩阵的元素和, 最小值, 最大值 ...
  • lwt36
  • lwt36
  • 2015年09月15日 00:28
  • 379

UVa 11992 Fast Matrix Operations(两种标记的线段树)

本题涉及到了线段数大多数基本操作。 因为只有20行,所以可以建20个线段树。 线段树最重要的两个函数: pushdown 下移标记,并更新子节点数据。 pushup  由2个子节点数据更新父节点数据。...

uva 11992 Fast Matrix Operations(线段树)

模板题:区间

UVA 11992 Fast Matrix Operations (线段树区间更新)

刘汝佳白书上的题目。 题意 : 给你一个矩阵(m * n,最多20行,总元素不超过10^6个),然后Q次操作。有3种操作 : 1,在(x1,y1)~(x2,y2)这个子矩阵上每一个元素都加上 v。 2...

[线段树双lazy]UVa11992 - Fast Matrix Operations

题意: 三种操作在矩阵上进行。添加val,set val,查询。分析: 裸线段树,但是做完后发现别人都用的一维的,而我却封装了用的二维的。。。。也是醉了,数据再大点的话就存不...

Uva 11992 Fast Matrix Operations(线段树区间设值与加操作)

题目链接Uva 11992 Fast Matrix Operations因为同时有加和赋值操作,所以在下推标记时要注意,应先考虑赋值操作,再考虑加 而在更新的时候如果,是赋值更新,则会清除加标记,...

Uva 11992 - Fast Matrix Operations题解(线段树区间更新+区间Set+Add,查询最大值,最小值,总和)

Problem F Fast Matrix Operations There is a matrix containing at most 106 elements divided into ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UVA 11992 Fast Matrix Operations 线段树
举报原因:
原因补充:

(最多只允许输入30个字)