Fast Matrix Operations
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));
*/
}
}
}
}
需要注意的是:
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的更多相关文章
- UVA 11992 - Fast Matrix Operations(段树)
UVA 11992 - Fast Matrix Operations 题目链接 题意:给定一个矩阵,3种操作,在一个矩阵中加入值a,设置值a.查询和 思路:因为最多20列,所以全然能够当作20个线段树 ...
- UVA11992 - Fast Matrix Operations(段树部分的变化)
UVA11992 - Fast Matrix Operations(线段树区间改动) 题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v ...
- uva 11992 Fast Matrix Operations 线段树模板
注意 setsetset 和 addvaddvaddv 标记的下传. 我们可以控制懒惰标记的优先级. 由于 setsetset 操作的优先级高于 addaddadd 操作,当下传 setsetset ...
- Fast Matrix Operations(UVA)11992
UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y ...
- 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations
题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...
- UVA 11992 Fast Matrix Operations(线段树:区间修改)
题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=s ...
- UVA 11992 Fast Matrix Operations (二维线段树)
解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...
- UVa 11992 (线段树 区间修改) Fast Matrix Operations
比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递 ...
- uva 11992 - Fast Matrix Operations
简单的线段树的题: 有两种方法写这个题,目前用的熟是这种慢点的: 不过不知道怎么老是T: 感觉网上A过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...
随机推荐
- 应注意的Flex&Bison潜规则
1.Flex的二义性模式 语法分析器匹配输入时匹配尽可能多的字符串 如果两个模式都可以匹配的话,匹配在程序中更早出的模式. 针对这一点的理解,在语法分析文件当中,token的识别,应从特殊到一般的过程 ...
- 2014-10 u-boot make过程分析
/** ****************************************************************************** * @author Maox ...
- H5 适配 动画animation js touch
图片预加载jquery插件 jquery.imgpreload var load_img = [];load_img.push('http://m.pubuzhixing.com/Images/vot ...
- SQL Server 2008 R2密钥序列号
SQL Server 2008 R2密钥序列号 序列号: 开发版(Developer): PTTFM-X467G-P7RH2-3Q6CG-4DMYB 企业版(Enterprise): JD8Y6-HQ ...
- CentOS-6.3安装配置Nginx
安装说明 系统环境:CentOS-6.3软件:nginx-1.2.6.tar.gz安装方式:源码编译安装 安装位置:/usr/local/nginx 下载地址:http://nginx.org/en/ ...
- ShowMask
<html> <head> <script type="text/javascript"> function showMask(){ var a ...
- Catalyst揭秘 Day1 Catalyst本地解析
Catalyst揭秘 Day1 Catalyst本地解析 今天开始讲下Catalyst,这是我们必须精通的内容之一: 在Spark2.x中,主要会以Dataframe和DataSet为api,无论是D ...
- 移植openssl
1.官网(ftp://ftp.openssl.org/source/old/0.9.x/)下载openssl-0.9.8k.tar.gz2.交叉编译openssl CC=arm-hisiv400-li ...
- div中加入iframe,可以实现Ajax的功能
div中加入iframe,可以实现Ajax的功能,如果查询的时候,比如说城市的选择,用Ajax去实现, 在.net 可以考虑用UpdatePanel,但是点击了查询刷新表格(表格需要重新刷新加载,非纯 ...
- PHP微信开发代码
1,SAE上申请服务器 2,绑定测试账号 3,Token验证 <?php /* http://www.cnblogs.com/xrhou12326/ CopyRight 2014 All Rig ...