Fast Matrix Operations

时间:2023-02-15 17:46:01

A Simple Problem with Integers

每次将区间向下更新,或是用之前的方法,统计当前节点到父节点处的覆盖数目。

#include <cstdio>
#include <iostream>
using namespace std; const int MAXN = ; typedef long long int64; int d[MAXN]; class SegNode {
public:
int L, R;
int64 c, sum;
int64 get_c() { return c * (R - L + ); }
void log(const char *info) {
printf("%s: [%d %d]: %lld, %lld.\n", info, L, R, c, sum);
}
} node[MAXN * ]; class SegTree {
public:
void log(const char *info) {
printf("%s:\n", info);
printf("{%d %d}, %lld, %lld.\n", node[].L, node[].R, node[].c, node[].sum);
}
void build(int r, int L, int R) {
node[r].L = L;
node[r].R = R;
node[r].c = ;
if (L == R) {
node[r].sum = d[L];
} else {
int M = (L + R) / ;
build( * r, L, M);
build( * r + , M + , R);
node[r].sum = node[ * r].sum + node[ * r + ].sum;
}
}
int64 query(int r, int L, int R) {
if (L <= node[r].L && node[r].R <= R) {
return node[r].sum + node[r].get_c();
} else {
node[ * r].c += node[r].c;
node[ * r + ].c += node[r].c;
int64 res = ;
if (L <= node[ * r].R) {
res += query( * r, L, R);
}
if (R >= node[ * r + ].L) {
res += query( * r + , L, R);
}
node[r].c = ;
node[r].sum = node[ * r].sum + node[ * r + ].sum + node[ * r].get_c() + node[ * r + ].get_c();
//node[r].log("query");
return res;
}
}
void insert(int r, int L, int R, int c) {
if (L <= node[r].L && node[r].R <= R) {
node[r].c += c;
} else {
node[ * r].c += node[r].c;
node[ * r + ].c += node[r].c;
if (L <= node[ * r].R) {
insert( * r, L, R, c);
}
if (R >= node[ * r + ].L) {
insert( * r + , L, R, c);
}
node[r].c = ;
node[r].sum = node[ * r].sum + node[ * r + ].sum + node[ * r].get_c() + node[ * r + ].get_c();
}
//log("tree");
//node[r].log("insert");
}
/*{{{ insert2*/
void insert2(int r, int L, int R, int c) {
if (L <= node[r].L && node[r].R <= R) {
node[r].c += c;
} else {
if (L <= node[ * r].R) {
insert( * r, L, R, c);
}
if (R >= node[ * r + ].L) {
insert( * r + , L, R, c);
}
node[r].sum = node[ * r].sum + node[ * r + ].sum + node[ * r].get_c() + node[ * r + ].get_c();
}
}
/*}}}*/
/*{{{ query2*/
int64 query2(int r, int L, int R, int dd) {
dd += node[r].c;
if (L <= node[r].L && node[r].R <= R) {
return node[r].sum + (node[r].R - node[r].L + ) * dd;
} else {
int res = ;
if (L <= node[ * r].R) {
res += query( * r, L, R);
}
if (R >= node[ * r + ].L) {
res += query( * r + , L, R);
}
return res;
}
}
/*}}}*/
}; int main() {
int n, q;
while (scanf("%d%d", &n, &q) != EOF) {
SegTree tree;
for (int i = ; i <= n; i++) scanf("%d", &d[i]);
tree.build(, , n);
while (q--) {
char ch[];
int a, b;
scanf("%s%d%d", ch, &a, &b);
if (ch[] == 'C') {
int c;
scanf("%d", &c);
tree.insert(, a, b, c);
//tree.insert2(1, a, b, c);
} else if (ch[] == 'Q') {
printf("%lld\n", tree.query(, a, b));
/*
int dd = 0;
printf("%lld\n", tree.query2(1, a, b, dd));
*/
}
}
}
}

Fast Matrix Operations

需要注意的是:

1. 插入及查询在树上向下遍历时,不然是否有遍历,都应该将节点上的覆盖数目向下传递;

2. 树构建的时候,一些节点会构建不出来,这种类型的节点,在插入向孩子节点遍历的时候,之前判断失败的条件,可能会判断成功,从而导致错误;

3. 节点中的sum表示的是当前节点构成的树除了当前节点上的覆盖数以外的所有数的和。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long int64; class SegNode {
public:
int L, R, B, T;
int64 v, m_min, m_max, m_sum;
bool is_clear;
SegNode* sons[];
SegNode() {
v = m_min = m_max = m_sum = ;
is_clear = false;
memset(sons, NULL, sizeof(sons));
}
int area() {
return (R - L + ) * (T - B + );
}
}; class SegTree {
public:
void free(SegNode *node) {
for (int i = ; i < ; i++) {
if (node->sons[i] != NULL) {
free(node->sons[i]);
}
}
if (node != NULL) {
delete node;
node = NULL;
}
}
void build(SegNode* &node, int L, int R, int B, int T) {
node = new SegNode();
node->L = L; node->R = R; node->B = B; node->T = T;
if (L == R && B == T) {
// leaf
} else {
// non leaf
int M1 = (L + R) / ;
int M2 = (B + T) / ;
if (L <= M1 && M2 + <= T) build(node->sons[], L, M1, M2 + , T);
if (M1 + <= R && M2 + <= T) build(node->sons[], M1 + , R, M2 + , T);
if (L <= M1 && B <= M2) build(node->sons[], L, M1, B, M2);
if (M1 + <= R && B <= M2) build(node->sons[], M1 + , R, B, M2);
}
}
void insert(SegNode *node, int L, int R, int B, int T, int v, int k) {
//node->log();
if (L <= node->L && node->R <= R && B <= node->B && node->T <= T) {
if (k == ) node->v += v;
else if (k == ) {
node->v = v;
node->m_min = node->m_max = node->m_sum = ;
node->is_clear = true;
}
} else {
int M1 = (node->L + node->R) / ;
int M2 = (node->B + node->T) / ;
for (int i = ; i < ; i++) {
if (node->sons[i] != NULL) {
down(node, node->sons[i]);
}
}
if (L <= M1 && T >= M2 + ) {
if (node->sons[] != NULL)
insert(node->sons[], L, R, B, T, v, k);
}
if (R >= M1 + && T >= M2 + ) {
if (node->sons[] != NULL)
insert(node->sons[], L, R, B, T, v, k);
}
if (L <= M1 && B <= M2) {
if (node->sons[] != NULL)
insert(node->sons[], L, R, B, T, v, k);
}
if (R >= M1 + && B <= M2) {
if (node->sons[] != NULL)
insert(node->sons[], L, R, B, T, v, k);
}
// clear node[r]
node->is_clear = false;
node->v = ;
update(node);
}
}
void down(SegNode *r, SegNode *t) {
r->is_clear;
if (r->is_clear) {
t->is_clear = true;
t->v = r->v;
//
t->m_min = t->m_max = t->m_sum = ;
} else {
t->v += r->v;
}
}
void update(SegNode *r) {
bool need = true;
for (int i = ; i < ; i++) {
if (r->sons[i] != NULL) {
if (need) {
need = false;
r->m_min = r->sons[i]->m_min + r->sons[i]->v;
r->m_max = r->sons[i]->m_max + r->sons[i]->v;
r->m_sum = r->sons[i]->m_sum + r->sons[i]->v * r->sons[i]->area();
} else {
r->m_min = min(r->m_min, r->sons[i]->m_min + r->sons[i]->v);
r->m_max = max(r->m_max, r->sons[i]->m_max + r->sons[i]->v);
r->m_sum += r->sons[i]->m_sum + r->sons[i]->v * r->sons[i]->area();
}
}
}
}
void query(SegNode *node, int L, int R, int B, int T, int64& mmin, int64& mmax, int64& msum) {
//node->log();
if (L <= node->L && node->R <= R && B <= node->B && node->T <= T) {
mmin = min(mmin, node->m_min + node->v);
mmax = max(mmax, node->m_max + node->v);
msum += node->m_sum + node->v * node->area();
} else {
int M1 = (node->L + node->R) / ;
int M2 = (node->B + node->T) / ;
for (int i = ; i < ; i++) {
if (node->sons[i] != NULL) {
down(node, node->sons[i]);
}
}
if (L <= M1 && T >= M2 + ) {
if (node->sons[] != NULL)
query(node->sons[], L, R, B, T, mmin, mmax, msum);
}
if (R >= M1 + && T >= M2 + ) {
if (node->sons[] != NULL)
query(node->sons[], L, R, B, T, mmin, mmax, msum);
}
if (L <= M1 && B <= M2) {
if (node->sons[] != NULL)
query(node->sons[], L, R, B, T, mmin, mmax, msum);
}
if (R >= M1 + && B <= M2) {
if (node->sons[] != NULL)
query(node->sons[], L, R, B, T, mmin, mmax, msum);
}
// clear node[r]
node->is_clear = false;
node->v = ;
update(node);
}
}
}; int main() {
//freopen("fast.in", "r", stdin); int r, c, m;
while (scanf("%d%d%d", &r, &c, &m) != EOF) {
SegTree tree;
SegNode *root = NULL;
tree.build(root, , r, , c);
for (int i = ; i < m; i++) {
int k, x1, y1, x2, y2, v;
scanf("%d%d%d%d%d", &k, &x1, &y1, &x2, &y2);
if (k == ) {
int64 mmin = 1e9, mmax = -1e9, msum = ;
tree.query(root, x1, x2, y1, y2, mmin, mmax, msum);
printf("%lld %lld %lld\n", msum, mmin, mmax);
} else {
scanf("%d", &v);
tree.insert(root, x1, x2, y1, y2, v, k);
}
}
tree.free(root);
}
}

Fast Matrix Operations的更多相关文章

  1. UVA 11992 - Fast Matrix Operations&lpar;段树&rpar;

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

  2. UVA11992 - Fast Matrix Operations&lpar;段树部分的变化&rpar;

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

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

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

  4. Fast Matrix Operations&lpar;UVA&rpar;11992

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

  5. 线段树&lpar;多维&plus;双成段更新&rpar; UVA 11992 Fast Matrix Operations

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

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

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

  7. UVA 11992 Fast Matrix Operations &lpar;二维线段树&rpar;

    解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...

  8. UVa 11992 &lpar;线段树 区间修改&rpar; Fast Matrix Operations

    比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递 ...

  9. uva 11992 - Fast Matrix Operations

    简单的线段树的题: 有两种方法写这个题,目前用的熟是这种慢点的: 不过不知道怎么老是T: 感觉网上A过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...

随机推荐

  1. C&num;&period;NET 大型通用信息化系统集成快速开发平台 4&period;1 版本 - 角色成员功能的改进支持公司加入到角色

    我们公司有1万多个网点,每个网点都可以看成是一个公司,公司对不同的网点有不同的策略,商业逻辑,每个网点的人员也都是在不断变化,全国有接近10万从业人员,当我们设计好业务逻辑程序后,不可能因为这些人员的 ...

  2. printf&lpar;&quot&semi;&percnt;&ast;s&percnt;s&percnt;&ast;s&quot&semi;,——)是什么?

    我们可能知道scanf里用*修饰符,是起到过滤读入的作用.比如一个有三列数值的数据,我只想得到第2列数值,可以在循环里用scanf(“%*d%d%*d”, a[i])来读入第i行的第2个数值到a[i] ...

  3. Cocos2d-JS引入资源

    以图片为例: 创建项目后,把图片放入res文件夹,修改 app.js var HelloWorldLayer = cc.Layer.extend({ sprite:null, ctor:functio ...

  4. ios球体弹跳游戏源码

    一款耐玩的ios游戏源码,画面上有很多小星星,球体落下的时候,你需要在画面上画出一条条的线条让球体弹跳起来然后吃掉小星星,如果没借助球体就失败了.游戏有很多关卡.注意: <ignore_js_o ...

  5. 段落排版--中文字间距、字母间距&lpar;letter-spacing&comma; word-spacing&rpar;

    中文字间隔.字母间隔设置: 如果想在网页排版中设置文字间隔或者字母间隔就可以使用    letter-spacing 来实现,如下面代码: h1{ letter-spacing:50px; } ... ...

  6. 如何在开发时部署和运行前后端分离的JavaWeb项目

    在开发中大型的JavaEE项目时,前后端分离的框架逐渐成为业界的主流,传统的单机部署前后端在同一个项目中的工程项目越来越少.这类JavaWeb项目的后端通常都采用微服务的架构,后端会被分解为诸多个小项 ...

  7. Python不同目录间模块调用

    #!/usr/bin/python # -*- coding: utf-8 -*- # 导入其它目录下的文件, 需要去帮获取当前程序的绝对路径并加入到环境变量的相对路径中 import os impo ...

  8. c&num; 扩展方法初见理解

    个人理解扩展方法是对某些类在不改变源码的基础上添加其他的方法.扩展方法必须是在非泛型的静态类里定义,且第一个参数是要使用this 指定需要扩展的类型. class Program { static v ...

  9. WPF使用样式更新ArcGis InfoWindow外观代码

    <Style x:Key="mainInfoWindowStyleMF" TargetType="{x:Type esri:InfoWindow}"&gt ...

  10. vue常用属性解释。

    props:详看 示例-网格组件. props 可以是数组或对象,用于接收来自父组件的数据.props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测.自定义校验和设置默认值 ...