UVA 11992 线段树
input
r c m r<=20,1<=m<=20000
m行操作
1 x1 y1 x2 y2 v add v
2 x1 y1 x2 y2 v set v
3 x1 y1 x2 y2 查询该矩阵中的sum,max,min
output
对于每个3操作输出sum,max,min
做法:每行建一颗线段树
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#define INF 0x7fffffff
#define MAX 1000000 using namespace std; struct node
{
int v,addv,setv,sum,min,max;
};
int r,c,m,x1,yy1,x2,yy2,v,op,suma,mina,maxa;
node a[][MAX*];
void pushdown(int &l,int &r,int &k,int&i)
{
if(a[i][k].setv==&&a[i][k].addv==) return;
int m=l+((r-l)>>),lc=k<<,rc=k<<|,allv=a[i][k].setv+a[i][k].addv;
if(a[i][k].setv) //有set操作时优先将set操作pushdown
{
a[i][lc].addv=a[i][rc].addv=a[i][k].addv;
a[i][lc].v=a[i][rc].v=a[i][lc].setv=a[i][rc].setv=a[i][k].setv;
a[i][lc].min=a[i][rc].min=a[i][lc].max=a[i][rc].max=allv;
a[i][lc].sum=(m-l+)*allv;
a[i][rc].sum=(r-m)*allv;
a[i][k].setv=a[i][k].addv=;
}
else //无set操作时只是add操作也要pushdown
{
a[i][lc].addv+=a[i][k].addv;
a[i][rc].addv+=a[i][k].addv;
a[i][lc].min+=a[i][k].addv;
a[i][rc].min+=a[i][k].addv;
a[i][lc].max+=a[i][k].addv;
a[i][rc].max+=a[i][k].addv;
a[i][lc].sum+=(m-l+)*a[i][k].addv;
a[i][rc].sum+=(r-m)*a[i][k].addv;
a[i][k].addv=;
}
// printf("l:%d r:%d setv:%d add:%d\n",l,r,a[i][k].setv,a[i][k].addv);
}
void reset(int &l,int &r,int &k,int&i)
{
int m=l+((r-l)>>),lc=k<<,rc=k<<|;
a[i][k].sum=a[i][lc].sum+a[i][rc].sum+(r-l+)*a[i][k].addv;
a[i][k].min=min(a[i][lc].min,a[i][rc].min)+a[i][k].addv;
a[i][k].max=max(a[i][lc].max,a[i][rc].max)+a[i][k].addv;
}
void setupdate(int l,int r,int k,int &i)
{
int lc=k<<,rc=k<<|;
if(yy1<=l&&yy2>=r)
{
a[i][k].min=a[i][k].max=a[i][k].setv=a[i][k].v=v;
a[i][k].addv=;
a[i][k].sum=(r-l+)*v;
//printf("l:%d r:%d setv:%d add:%d\n",l,r,a[i][k].setv,a[i][k].addv);
return;
}
pushdown(l,r,k,i);
int m=l+((r-l)>>);
if(yy1<=m) setupdate(l,m,lc,i);
if(yy2>m) setupdate(m+,r,rc,i);
reset(l,r,k,i);
}
void addupdate(int l,int r,int k,int &i)
{
int lc=k<<,rc=k<<|;
if(yy1<=l&&yy2>=r)
{
a[i][k].addv+=v;
a[i][k].sum+=(r-l+)*v;
a[i][k].min+=v;
a[i][k].max+=v;
return;
}
pushdown(l,r,k,i);
int m=l+((r-l)>>);
if(yy1<=m) addupdate(l,m,lc,i);
if(yy2>m) addupdate(m+,r,rc,i);
reset(l,r,k,i);
}
void query(int l,int r,int k,int& i,int add)
{
if(a[i][k].setv)
{
int allv=add+a[i][k].v+a[i][k].addv;
suma+=allv*(min(r,yy2)-max(l,yy1)+);
mina=min(mina,allv);
maxa=max(maxa,allv);
//printf("addv:%d all:%d %d %d\n",a[i][k].addv,add,mina,maxa);
return;
}
if(yy1<=l&&yy2>=r)
{
suma+=a[i][k].sum+(r-l+)*add;
mina=min(mina,a[i][k].min+add);
maxa=max(maxa,a[i][k].max+add);
return;
}
int m=l+((r-l)>>);
if(yy1<=m) query(l,m,k<<,i,add+a[i][k].addv);
if(yy2>m) query(m+,r,k<<|,i,add+a[i][k].addv);
}
int main()
{
freopen("/home/user/桌面/in","r",stdin);
while(scanf("%d%d%d",&r,&c,&m)==)
{
for(int i=;i<=r;i++) memset(a[i],,sizeof(a[][])**c);
//memset(a,0,sizeof(a));
while(m--)
{
scanf("%d%d%d%d%d",&op,&x1,&yy1,&x2,&yy2);
if(op==)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++) setupdate(,c,,i);
//for(int i=1;i<3*c;i++) printf("%d:%d %d\n",i,a[3][i].setv,a[3][i].addv);
//puts("set");
}
else if(op==)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++) addupdate(,c,,i);
//for(int i=1;i<3*c;i++) printf("%d:%d %d\n",i,a[3][i].setv,a[3][i].addv);
//puts("add");
}
else
{
suma=;
mina=INF;
maxa=-INF-;
//printf("row:%d-%d\ncol:%d-%d\n",x1,x2,yy1,yy2);
//for(int i=1;i<=r;i++) printf("rowsum:%d\n",a[i][1].sum);
for(int i=x1;i<=x2;i++) query(,c,,i,);
printf("%d %d %d\n",suma,mina,maxa);
}
}
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return ;
}
UVA 11992 线段树的更多相关文章
- UVa 11992 (线段树 区间修改) Fast Matrix Operations
比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递 ...
- UVA 11992 ——线段树(区间修改)
解题思路: 将矩阵每一行建立一棵线段树,进而变成一维问题求解.注意数组要开 4*N 代码如下: #include <iostream> #include <cstdio> #i ...
- Fast Matrix Operations UVA - 11992 线段树
题意翻译 有一个r行c列的全0矩阵,有以下三种操作. 1 X1 Y1 X2 Y2 v 子矩阵(X1,Y1,X2,Y2)的元素加v 2 X1 Y1 X2 Y2 v 子矩阵(X1,Y1,X2,Y2)的元素 ...
- uva 11525(线段树)
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 11297 线段树套线段树(二维线段树)
题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要 不同的处理方式,非叶子形成的 ...
- UVa 1400 (线段树) "Ray, Pass me the dishes!"
求一个区间的最大连续子序列,基本想法就是分治,这段子序列可能在区间的左半边,也可能在区间的右半边,也有可能是横跨区间中点,这样就是左子区间的最大后缀加上右子区间的最大前缀之和. 线段树维护三个信息:区 ...
- uva 1513(线段树)
题目链接:1513 - Movie collection 题意:有一堆电影,按1-n顺序排,有m次操作,每次询问第ai个电影之前有多少个电影,然后将其抽出放在堆顶. 分析:线段树应用. 因为每次查询后 ...
- uva 12086 线段树or树状数组练习
题目链接 https://vjudge.net/problem/34215/origin 这个题就是线段树裸题,有两种操作,实现单点更新和区间和的查找即可,这里第一次学习使用树状数组完成. 二者相 ...
- UVa 12299 线段树 单点更新 RMQ with Shifts
因为shift操作中的数不多,所以直接用单点更新模拟一下就好了. 太久不写线段树,手好生啊,不是这错一下就是那错一下. PS:输入写的我有点蛋疼,不知道谁有没有更好的写法. #include < ...
随机推荐
- input编辑框编辑状态切换
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- delphi edit 中undo 和clearundo 复制粘贴等总结
edit 和memo都有undo功能, Undo:恢复到改动前. ClearUndo:撤销掉Undo缓冲区的内容,则将无法恢复到改动前的 从该文本框的撤销缓冲区中清除关于最近操作的信息,根据应用 程序 ...
- Java 字符串比较,String 中的一些方法 == 和 equals 的详解
"==" 是比较的是两个对象的内存地址,而equals方法默认情况下是比较两个对象的内存地址. 1.String str = "hello" 生成的字符串,首 ...
- NOIP2002-普及组复赛-第三题-选数
题目描述 Description 已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和.例如当 n=4,k=3,4 个整 ...
- 菲菲更名宝贝(批量更名软件) v8.0 绿色版
软件名称: 菲菲更名宝贝(批量更名软件)软件语言: 简体中文授权方式: 免费软件运行环境: Win7 / Vista / Win2003 / WinXP 软件大小: 1.5MB图片预览: 软件简介:菲 ...
- 消除警告"property access result unused - getters should not be used for side effects"
我写了如下一段代码: - (void)btnClicked:(UIButton *)button { switch (button.tag) { : self.initShare; break; de ...
- 将MyEclipse中的项目导入到Eclipse中报错的解决放法
1.导入项目后,会报红色感叹号, 将项目右键,点击红色框.
- C++模板之类型与数据绑定
有时候我们需要将类型与一些数据进行绑定,例如我们一般通过单例,将字符串与一个函数关联(一般称之为注册),之后通过字符串创建相关联的对象 class A { public: static A* Crea ...
- angular中重要指令介绍($eval,$parse和$compile)
在angular的服务中,有一些服务你不得不去了解,因为他可以说是ng的核心,而今天,我要介绍的就是ng的两个核心服务,$parse和$compile.其实这两个服务讲的人已经很多了,但是100个读者 ...
- Learning BSD.sys/queue.h
This file includes 4 data-structures.. Insteresting because they are written in 1994.. to make it ea ...