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过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...
随机推荐
- SEO视频教程集合在线观看
seo是搜索引擎优化(Search Engine Optimization)的英文缩写,是指为了从搜索引擎中获得更多的免费流量,从网站结构.内容建设方案.用户互动传播.页面等角度进行合理规划,使网站更 ...
- RestFul && HATEOAS && Spring-Data-Rest介绍
1.什么是RestFul 经常上网的同学会发现,现代软件的一个重要趋势就是互联网化,几乎没有一款软件是纯粹的单机版了.通常的情况下,软件管理着服务器的资源以及这些资源的状态变化,用户通过在浏览器输入h ...
- C#对象转JSON字符串和JSON字符串转对象
namespace Net.String.ConsoleApplication { using System; using System.Data; using System.Collections; ...
- 使用XFire+Spring构建Web Service
XFire是与Axis 2并列的新一代Web Service框架,通过提供简单的API支持Web Service各项标准协议,帮助你方便快速地开发Web Service应用. 相 对于Axis来说,目 ...
- WPF处理Windows消息
WPF中处理消息首先要获取窗口句柄,创建HwndSource对象 通过HwndSource对象添加消息处理回调函数. HwndSource类: 实现其自己的窗口过程. 创建窗口之后使用 AddHook ...
- 解决WPF图片模糊最佳方法(绑定PixelWidth与PixelHeight)
从事WPF开发一年有余,对于图片显示模糊相信很多人都遇到过.网络上查找能得到一堆解决方法,但都是会带来其他负面影响得不到最佳效果.其实,有些图片会因为垂直分辨率/水平分辨率不同而造成在WPF界面上显示 ...
- 1076. Forwards on Weibo (30)
时间限制 3000 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Weibo is known as the Chinese v ...
- 【BZOJ 1040】 [ZJOI2008]骑士
Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...
- python解决汉诺塔问题
今天刚刚在博客园安家,不知道写点什么,前两天刚刚学习完python 所以就用python写了一下汉诺塔算法,感觉还行拿出来分享一下 首先看一下描述: from :http://baike.baidu. ...
- Xcode界面简介
创建 Object-C 程序 进入主界面方式 : 打开 Xcode 之后, 可以使用 Xcode 菜单, 但是必须创建一个 Object-C 工程 或者 导入 一个 Object-C 工程才可以进入主 ...