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(段树)

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

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

    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(UVA)11992

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

  5. 线段树(多维+双成段更新) 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 (二维线段树)

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

  8. UVa 11992 (线段树 区间修改) Fast Matrix Operations

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

  9. uva 11992 - Fast Matrix Operations

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

随机推荐

  1. 膜拜 2014-2 (献给L之三)

    文/安然 深深的夜静静的想你细细的品味满满的甜蜜爱,心灵的对话让我流泪战栗谢谢你给我这么弥足珍贵的体会不能一生相随又有什么关系你一直都在我的爱就永不停息此生足以——献给心底的爱

  2. linux同步

    1. 内核同步 主要是防止多核处理器同时访问修改某段代码,或者在对设备驱动程序进行临界区的保护. 1 .互斥量 头文件 #include<linux/mutex.h> 初始化方法: 静态初 ...

  3. ArcGIS Server10.1授权文件

    3dengine,101,ecp.arcgis.server,01-jan-2020,UTE784S3EY83ZJKN0085 3dserver,101,ecp.arcgis.server,01-ja ...

  4. Android 核心组件 Activity 之上

    核心组件的特征 1. 必须继承自特定的类(Activity 或者 Activity的子类) 2. 必须注册: 通常是AndroidManifest.xml的 <application> 中 ...

  5. aliexpress 上传图

    首先,图片转化为字节流 public byte[] ImagefileToByte(string srcImagePath) { System.IO.MemoryStream m = new Syst ...

  6. java 中的匿名内部类

    转自http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能 ...

  7. ARM-Linux S5PV210 UART驱动(2)---- 终端设备驱动

    在Linux中,UART串口驱动完全遵循tty驱动的框架结构,但是进行了底层操作的再次封装,所以先介绍tty终端设备驱动. 一.终端设备 1.串行端口终端(/dev/ttySACn) 2.伪终端(/d ...

  8. Teradata基础教程中的数据库试验环境脚本

    Teradata基础教程中的数据库表: Customer:  客户信息表 Location:  位置信息表 Employee:  雇员信息表 Job:  工作信息表 Department:  部门表 ...

  9. 十六、mysql 分区之 简单sql优化2

    .索引的分类 B-Tree 基本支持 HASH 只有memory支持 R-Tree myisam支持 Full-text myisam支持(全文索引) .Memory引擎下只有“=”条件才会使用索引 ...

  10. MS SQL Server时间常用函数

    SQLServer时间日期函数详解,SQLServer,时间日期, 1.      当前系统日期.时间 select getdate() 2. dateadd      在向指定日期加上一段时间的基础 ...