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**/
- Uva 11992 - Fast Matrix Operations题解(线段树区间更新+区间Set+Add,查询最大值,最小值,总和)
- UVA 11992 Fast Matrix Operations (线段树区间更新)
- uva 11992 Fast Matrix Operations (线段树区间更新)
- uva 11992 Fast Matrix Operations(线段树,区间修改)
- UVA - 11992 Fast Matrix Operations 线段树(区间修改)
- Fast Matrix Operations uva+线段树区间修改
- Uva11992 Fast Matrix Operations(线段树区间修改+更新)
- uva 1401 Fast Matrix Operations 快速矩阵操作 (线段树 区间修改和查询)
- UVA 11992- Fast Matrix Operations(线段树区间各种操作)
- UVA 11992(Fast Matrix Operations-线段树区间加&改)[Template:SegmentTree]
- UVa 11992 Fast Matrix Operations (线段树区间修改大杂烩)
- Uva 11992 Fast Matrix Operations(线段树区间设值与加操作)
- uva11992 - Fast Matrix Operations 区间修改 二维线段树
- UVA11992 - Fast Matrix Operations(线段树区间修改)
- uva 11992 Fast Matrix Operations(线段树)
- UVa 11992 Fast Matrix Operations 线段树
- UVA 11992 - Fast Matrix Operations(线段树)
- uva 11992 Fast Matrix Operations 线段树
- GlowPadView 分析
- poj 2456 Aggressive cows(贪心+二分)
- android 侧滑菜单实现
- U盘启动盘制作及系统安装
- 对称子字符串的最大长度
- Uva 11992 - Fast Matrix Operations题解(线段树区间更新+区间Set+Add,查询最大值,最小值,总和)
- 第二章:线性表
- 特殊的js用法技巧
- zoj 2297
- javascript第三方获取用户ip
- Android:android自定义滑动开关控件
- 黑马程序员--IO流之File类
- an error has occurred.see error log的解决办法
- 机器学习之旅---朴素贝叶斯分类器