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过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...
随机推荐
- host文件的作用和介绍
在Window系统中有个Hosts文件(没有后缀名)在Windows98系统下该文件在Windows目录,在Windows2000/XP系统中位于C:\Winnt\System32\Drivers\E ...
- hibernate的运行流程
首先了解什么是对象关系映射,ORM(Object/Relationship Mapping):对象关系映射.对象关系映射是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术.是通过使用描述对象 ...
- UVALive 6811 Irrigation Line(二分图最小点覆盖--匈牙利算法)
题意:求最少的线可以覆盖一个由0.1两种数字组成的图中所有的1. eg: 只需要两条线即可. 分析: 1.先为上述例子的行列标号 2.若图中数字为1,则代表该数字所在的行与列有关联. 例如第r1行第c ...
- (hdu)5423 Rikka with Tree (dfs)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5423 Problem Description As we know, Rikka is p ...
- Bugzilla+MySql+IIS+ActivePerl搭建指南
头在忙着他的技术研究,对团队建设.测试管理.流程规范都不怎么理会,眼见着产品进入后期整合阶段,在测试过错中出现很多Bug,单靠着我一个人用txt来收集整理bug需求,然后整理成word,放在svn上面 ...
- NTT研发
2.研发标准 stead---大型机 css terasolunt---反向自动生成设计书 3.开发阶段做好设计,确定需求,测试阶段只是做产品有多差或者完成了多少需求,不是用来提高产品质量的过程
- mysql 主从同步 Last_SQL_Error
参考文章: http://kerry.blog.51cto.com/172631/277414/ http://hancang2010.blog.163.com/blog/static/1824602 ...
- php100 编程小技巧
用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则 不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中 ...
- StringBuilder的Append()方法会比+=效率高
StringBuilder strSql = new StringBuilder(); strSql.Append("select top 1 id from " + databa ...
- ToolStripStatusLabel设置时间自动更新
在使用委托设置界面上ToolStripStatusLabel类型的控件时间是,发现不能使用自定义的委托方法,在往上查找了一下发现不能使用involve来线程调用.因此只能使用原生委托方法. //代理p ...