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

来源:互联网 发布:免费人事工资软件 编辑:程序博客网 时间:2024/05/20 11:25

Problem F

Fast Matrix Operations

There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operations:

1 x1 y1 x2 y2 v

Increment each element (x,y) in submatrix (x1,y1,x2,y2) by v (v>0)

2 x1 y1 x2 y2 v

Set each element (x,y) in submatrix (x1,y1,x2,y2) to v

3 x1 y1 x2 y2

Output the summation, min value and max value of submatrix (x1,y1,x2,y2)

In the above descriptions, submatrix (x1,y1,x2,y2) means all the elements (x,y) satisfying x1<=x<=x2 and y1<=x<=y2. It is guaranteed that 1<=x1<=x2<=r, 1<=y1<=y2<=c. After any operation, the sum of all the elements in the matrix does not exceed 109.

Input

There are several test cases. The first line of each case contains three positive integers r, c, m, where m (1<=m<=20,000) is the number of operations. Each of the next m lines contains a query. There will be at most twenty rows in the matrix. The input is terminated by end-of-file (EOF). The size of input file does not exceed 500KB.

Output

For each type-3 query, print the summation, min and max.

Sample Input

4 4 81 1 2 4 4 53 2 1 4 41 1 1 3 4 23 1 2 4 43 1 1 3 42 2 1 4 4 23 1 2 4 41 1 1 4 3 3

Output for the Sample Input

45 0 578 5 769 2 739 2 7

Rujia Liu's Present 3: A Data Structure Contest Celebrating the 100th Anniversary of Tsinghua University
Special Thanks: Yeji Shen, Dun Liang

Note: Please make sure to test your program with the gift I/O files before submitting!

题意:

1 x1 y1 x2 y2 v 给矩阵 x1 y1 x2 y2的所有值加上v

2 x1 y1 x2 y2 v 把矩阵x1 y1 x2 y2置为(Set)v

3 x1 y1 x2 y2 查询矩阵x1 y1 x2 y2的总和,最小值,最大值

题解:

由于题目保证不超过20行,矩阵的数据总的不超过10^6个,有m=2*10^5次操作,那么用线段树做.

给每行建一棵线段树。

注意:

在add操作中不清除Set标记,在Set操作中要清除add标记。在query操作中要综合考虑add和Set。

在Set和add操作中,找到相应的区间后要先考虑Set,在考虑add(因为在Set的时候会把add的值清空,那么add是Set之后的操作)

时间复杂度

mlogn

#include<stdio.h>#include<algorithm>#include<math.h>#define MAX 1000000#define LL long long int#define INF 0x7f7f7fusing namespace std;int tMin,tMax;struct node{    int left,right;    int sum, add;    int Min,Max;    int Set;//Set=-1表示该段没有被重置}arr[21][3*MAX];void build(int idx, int l, int r,int pos){    arr[pos][idx].left = l, arr[pos][idx].right = r;    arr[pos][idx].add = 0;    arr[pos][idx].Min=0;    arr[pos][idx].Max=0;    arr[pos][idx].sum=0;    arr[pos][idx].Set=-1;    if(l == r){        return ;    }    int mid = (l + r) >> 1;    build(idx * 2, l, mid,pos);    build(idx * 2 + 1, mid + 1, r,pos);}void pushDown(int idx,int pos){    int lc=idx*2;    int rc=idx*2+1;    if(arr[pos][idx].Set>=0){        arr[pos][lc].Set=arr[pos][rc].Set=arr[pos][idx].Set;        arr[pos][lc].add=arr[pos][rc].add=0;        arr[pos][idx].Set=-1;        arr[pos][lc].sum=(arr[pos][lc].right - arr[pos][lc].left + 1)*arr[pos][lc].Set;//由于是Set那么sum的值要重新赋值        arr[pos][rc].sum=(arr[pos][rc].right - arr[pos][rc].left + 1)*arr[pos][rc].Set;        arr[pos][lc].Min=arr[pos][lc].Set;//由于是Set,那么就直接复制        arr[pos][lc].Max=arr[pos][lc].Set;        arr[pos][rc].Min=arr[pos][rc].Set;        arr[pos][rc].Max=arr[pos][rc].Set;    }    if(arr[pos][idx].add>0){//注意此处的处理,免得加了两边,一定要先计算完了,在吧arr[pos][idx].add=0        arr[pos][lc].add+=arr[pos][idx].add;        arr[pos][rc].add+=arr[pos][idx].add;        arr[pos][lc].sum += (arr[pos][lc].right - arr[pos][lc].left + 1) * arr[pos][idx].add;        arr[pos][rc].sum += (arr[pos][rc].right - arr[pos][rc].left + 1) * arr[pos][idx].add;        arr[pos][lc].Min+=arr[pos][idx].add;//由于整段都增加add,那么最大值和最小值加上add,即可        arr[pos][lc].Max+=arr[pos][idx].add;        arr[pos][rc].Min+=arr[pos][idx].add;        arr[pos][rc].Max+=arr[pos][idx].add;        arr[pos][idx].add=0;    }}void set(int idx, int l, int r, int val,int pos){    if(arr[pos][idx].right < l||arr[pos][idx].left > r)        return ;    if(arr[pos][idx].left >= l&&arr[pos][idx].right <= r){        arr[pos][idx].sum=(arr[pos][idx].right-arr[pos][idx].left+1)*val;        arr[pos][idx].add=0;        arr[pos][idx].Set=val;        arr[pos][idx].Min=val;        arr[pos][idx].Max=val;        return ;    }    pushDown(idx,pos);    int lc=idx * 2,rc=idx * 2 + 1;    set(lc, l, r, val,pos);    set(rc, l, r, val,pos);    arr[pos][idx].sum = arr[pos][lc].sum + arr[pos][rc].sum;    arr[pos][idx].Min=min(arr[pos][lc].Min,arr[pos][rc].Min);    arr[pos][idx].Max=max(arr[pos][lc].Max,arr[pos][rc].Max);}void add(int idx, int l, int r, int val,int pos){    if(arr[pos][idx].right < l||arr[pos][idx].left > r)        return ;    if(arr[pos][idx].left >= l&&arr[pos][idx].right <= r){        arr[pos][idx].sum += (arr[pos][idx].right - arr[pos][idx].left + 1) * val;        arr[pos][idx].add += val;        arr[pos][idx].Min+=val;        arr[pos][idx].Max+=val;        //printf("pos=%d l=%d r=%d sum=%d add=%d min=%d max=%d\n",pos,arr[pos][idx].left,arr[pos][idx].right,arr[pos][idx].sum,arr[pos][idx].add,          // arr[pos][idx].Min, arr[pos][idx].Max);        return ;    }    pushDown(idx,pos);    int lc=idx * 2,rc=idx * 2 + 1;    add(lc, l, r, val,pos);    add(rc, l, r, val,pos);    arr[pos][idx].sum = arr[pos][lc].sum + arr[pos][rc].sum;    arr[pos][idx].Min=min(arr[pos][lc].Min,arr[pos][rc].Min);    arr[pos][idx].Max=max(arr[pos][lc].Max,arr[pos][rc].Max);    //printf("~~~~~~sum=%d min=%d max=%d\n",arr[pos][idx].sum,arr[pos][idx].Min,arr[pos][idx].Max);}int query(int idx, int l, int r,int pos){    if(arr[pos][idx].right < l||arr[pos][idx].left > r)        return 0;    if(arr[pos][idx].left >= l&&arr[pos][idx].right <= r){        tMin=min(tMin,arr[pos][idx].Min);        tMax=max(tMax,arr[pos][idx].Max);        return arr[pos][idx].sum;    }    pushDown(idx,pos);    //printf("add=%d sum1=%d sum2=%d\n",arr[pos][idx].add,arr[pos][idx * 2].sum , arr[pos][idx * 2 + 1].sum);    int x = query(idx * 2, l, r,pos);    int y = query(idx * 2 + 1, l, r,pos);    //printf("*****%d %d %d %d %d\n",idx,x,y,tMin,tMax);    return x + y;}int main(){    int r,c,m;    while(~scanf("%d %d %d",&r,&c,&m)){        for(int i=1;i<=r;i++){            build(1,1,c,i);        }        while(m--){            int op,x1,x2,y1,y2,v,ans;            scanf("%d",&op);            ans=0;            tMin=INF;            tMax=-INF;            if(op==1){                scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&v);                for(int i=x1;i<=x2;i++){                    add(1,y1,y2,v,i);                }            }else if(op==2){                scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&v);                for(int i=x1;i<=x2;i++){                    set(1,y1,y2,v,i);                }            }else if(op==3){                scanf("%d %d %d %d",&x1,&y1,&x2,&y2);                for(int i=x1;i<=x2;i++){                    int tmp=query(1,y1,y2,i);                    //printf("~~~~%d\n",tmp);                    ans+=tmp;                }                printf("%d %d %d\n",ans,tMin,tMax);            }        }    }return 0;}/**5 5 101 2 2 5 5 32 1 1 3 3 13 2 2 5 53 1 1 3 35 5 101 1 1 3 3 41 2 2 3 3 2**/



0 0
原创粉丝点击