• 题目链接:

    https://www.luogu.org/problemnew/show/UVA11992

  • 题目大意:

    一个r*c的矩阵,一开始元素都是0,然后给你m次三种操作,分别是将一个子矩阵中所有元素加上v,将一个子矩阵元素全部修改成v,询问一个子矩阵中所有元素和,最大值和最小值.

  • 思路:

    应该说是一道有点毒瘤的数据结构题(然而时限居然给了5s)了,虽然它的主体只是线段树。我们可以把每一行都看作一棵线段树,这样操作就十分方便了。

    然后就是修改值的操作,对于初学者可能有点棘手,但实际上并不难,我们同样可以用lazy_tag打标记。但是就有一些要注意的东西了,当我们打add(元素加值)标记时是不会影响set(修改值)标记的,但是我们在打set标记时无论你前面add标记是多少,此时就相当于作废,所以直接将add标记赋为0就好了,然后直接修改sum,mi和mx(分别记录该区间的和,最小值,最大值)。

    同时我们可以让query询问函数直接返回一个存了sum,mi,mx的结构体,这样就不用查三次了.

    同时还有一个去要注意的地方,正如我们前面分析的那样,每一行开一颗线段树,但是实际上你真的不能搞一个tree[maxn],然后每一个tree中存一个线段树的结构体,这样是绝壁会爆的(我一开始就这么搞),而是和平常一样搞一个存全部元素的数组,具体怎么做还请看代码,我自认为还是写的比较直观。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <vector>
using namespace std;
const int maxn=1000005;
const int inf=0xfffffff;
int r,c,m,v;
int L,R;
struct Tmp{
Tmp() : sum(0), mx(-inf),mi(inf) {}//构造函数,非常方便,强烈推荐
Tmp(int x,int y,int z) :sum(x),mx(y),mi(z) {}
int sum;
int mx,mi;
};//query询问时直接返回这个结构体就好了
int sum[maxn<<2],add[maxn<<2],set[maxn<<2],mx[maxn<<2],mi[maxn<<2];
inline void up(int now){
sum[now]=sum[now<<1]+sum[now<<1|1];
mx[now]=max(mx[now<<1],mx[now<<1|1]);
mi[now]=min(mi[now<<1],mi[now<<1|1]);
return ;
}
void build(int now,int l,int r){//其实build一点用也没有,请大家忽略
if(l==r){
mx[now]=0;//-inf;
mi[now]=0;//inf;
return ;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
up(now);
return ;
}
inline void down(int now,int ln,int rn){//注意看这个push_down函数
if(set[now]){//修改标记
sum[now<<1]=set[now]*ln;
sum[now<<1|1]=set[now]*rn;
set[now<<1]=set[now];
set[now<<1|1]=set[now];
add[now<<1]=add[now<<1|1]=0;
mx[now<<1]=mx[now<<1|1]=set[now];
mi[now<<1]=mi[now<<1|1]=set[now];
set[now]=0;
}
if(add[now]){//加值标记
sum[now<<1]+=add[now]*ln;
sum[now<<1|1]+=add[now]*rn;
add[now<<1]+=add[now];
add[now<<1|1]+=add[now];
mx[now<<1]+=add[now];
mi[now<<1]+=add[now];
mx[now<<1|1]+=add[now];
mi[now<<1|1]+=add[now];
add[now]=0;
}
return ;
}
void update_add(int now,int l,int r){
if(L<=l&&r<=R){
add[now]+=v;
sum[now]+=v*(r-l+1);
mx[now]+=v;
mi[now]+=v;
return ;
}
int mid=(l+r)>>1;
down(now,mid-l+1,r-mid);
if(L<=mid)update_add(now<<1,l,mid);
if(mid<R)update_add(now<<1|1,mid+1,r);
up(now);
return ;
}
void update_set(int now,int l,int r){
if(L<=l&&r<=R){
set[now]=v;
sum[now]=v*(r-l+1);
add[now]=0;
mx[now]=v;
mi[now]=v;
return ;
}
int mid=(l+r)>>1;
down(now,mid-l+1,r-mid);
if(L<=mid)update_set(now<<1,l,mid);
if(mid<R)update_set(now<<1|1,mid+1,r);
up(now);
return ;
}
Tmp query(int now,int l,int r){
if(L<=l&&r<=R){
return Tmp(sum[now],mx[now],mi[now]);//十分方便
}
int mid=(l+r)>>1;
down(now,mid-l+1,r-mid);
Tmp tmp;
int sum=0,mx=-inf,mi=inf;
if(L<=mid){
tmp=query(now<<1,l,mid);
sum+=tmp.sum;
mx=max(mx,tmp.mx);
mi=min(mi,tmp.mi);
}
if(mid<R){
tmp=query(now<<1|1,mid+1,r);
sum+=tmp.sum;
mx=max(mx,tmp.mx);
mi=min(mi,tmp.mi);
}
// up(now); //然而并不用up()
tmp.sum=sum,tmp.mi=mi,tmp.mx=mx;
return tmp;
}
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;
return ;
}
int main()
{
int op,x1,x2,y1,y2;
read(r),read(c),read(m);
// build(1,1,r*c);
while(m--){
read(op),read(x1),read(y1),read(x2),read(y2);
if(op==1){
read(v);
for(register int i=x1;i<=x2;i++){
L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
update_add(1,1,r*c); //r*c是所有元素的范围
}
}
else if(op==2){
read(v);
for(register int i=x1;i<=x2;i++){
L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
update_set(1,1,r*c);
}
}
else {
Tmp tmp;
int sum=0,mx=-inf,mi=inf;
for(register int i=x1;i<=x2;i++){
L=(i-1)*c+y1,R=(i-1)*c+y2; //注意处理技巧!!!
tmp=query(1,1,r*c);
sum+=tmp.sum;
mx=max(mx,tmp.mx);
mi=min(mi,tmp.mi);
}
printf("%d %d %d\n",sum,mi,mx);
}
}
return 0;
}

luogu题解 UVA11992 【Fast Matrix Operations】的更多相关文章

  1. UVA11992 - Fast Matrix Operations(段树部分的变化)

    UVA11992 - Fast Matrix Operations(线段树区间改动) 题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v ...

  2. [uva11992]Fast Matrix Operations(多延迟标记,二维线段树,区间更新)

    题目链接:https://vjudge.net/problem/UVA-11992 题意:n*m的矩阵,每次对一个子矩阵操作,有三种操作:加x,设置为x,查询.查询返回子矩阵和.最小值.最大值 n很小 ...

  3. UVA11992 Fast Matrix Operations

    思路 注意到最多20行,拆成20颗线段树即可 注意set标记清空左右儿子的add,不要清空自己的add,因为这个set操作之后可能还有add存在这个节点上 代码 #include <cstdio ...

  4. Fast Matrix Operations

    A Simple Problem with Integers 每次将区间向下更新,或是用之前的方法,统计当前节点到父节点处的覆盖数目. #include <cstdio> #include ...

  5. UVA 11992 - Fast Matrix Operations(段树)

    UVA 11992 - Fast Matrix Operations 题目链接 题意:给定一个矩阵,3种操作,在一个矩阵中加入值a,设置值a.查询和 思路:因为最多20列,所以全然能够当作20个线段树 ...

  6. uva 11992 Fast Matrix Operations 线段树模板

    注意 setsetset 和 addvaddvaddv 标记的下传. 我们可以控制懒惰标记的优先级. 由于 setsetset 操作的优先级高于 addaddadd 操作,当下传 setsetset ...

  7. Fast Matrix Operations(UVA)11992

    UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y ...

  8. 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

    题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...

  9. UVA 11992 Fast Matrix Operations(线段树:区间修改)

    题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=s ...

随机推荐

  1. centos-Hadoop集群 安装同步时间

    1.安装 yum search cache ntpdate xcall.sh "yum install -y ntpdate.x86_64" 2.同步 xcall.sh " ...

  2. Django中三种方式写form表单

    除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式 ...

  3. 图及其衍生算法(Graphs and graph algorithms)

    1. 图的相关概念 树是一种特殊的图,相比树,图更能用来表示现实世界中的的实体,如路线图,网络节点图,课程体系图等,一旦能用图来描述实体,能模拟和解决一些非常复杂的任务.图的相关概念和词汇如下: 顶点 ...

  4. redis 概述及部署 安装php和python客户端

    概述 Redis是一个基于key-value键值对的持久化数据库存储系统.redis支持的数据存储类型比memcached更丰富,包括strings(字符串),lists(列表),sets(集合)和s ...

  5. Oracle事务、视图、序列

    回顾什么是事务? 一个不可分割的子操作形成一个整体,该整体要么全部执行成功,要么全部执行失败.例如:转帐 回顾为什么要用事务? 如果不用事务的话,为转帐为例,可能出现一个用户钱增加了,另一个用户钱不变 ...

  6. Linux命令jobs小记

    命令使用过程中,输出中总是会带两个符号:+ 和 -,如: [1] 7893 Running gpass & [2] 7904 Running gnome-calculator & [3 ...

  7. Spring Boot启动的报错 Stopping service [Tomcat]

    我遇到的问题是项目中使用java_websocket的WebSocketClient,由于性能要求,需要再Controller直接继承WebSocketClient, 在项目启动过程中调试进入spri ...

  8. Linux学习—rpm包管理

    前言 在linux上,一个软件通常由二进制程序,库文件,配置文件和帮助文件组成.其中: 二进制程序一般都放在/bin,/sbin,/usr/bin,/usr/sbin,/usr/local/bin和/ ...

  9. bootstrap4 调整元素之间距离

    影响元素之间的间距是可以通过style的margin或padding属性来实现,但这两个属性本意并不相同:margin影响的是本元素与相邻外界元素之间的距离,这里简称外边距:padding影响的元素本 ...

  10. MySQL知识篇-SQL2

    1 数据库基本操作? (1) 查看数据库 show databases; (2)切换到指定的数据库 use dbname; (3)创建数据库 create database 库名 charset=ut ...