hdu1892(二维树状数组)

2024-09-07 19:58
文章标签 数组 树状 二维 hdu1892

本文主要是介绍hdu1892(二维树状数组),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

See you~

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3726    Accepted Submission(s): 1168

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1892
Problem Description
Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algorithm and Programming, and I met so many good friends. I want to say sorry to Mr, Yin, I must leave now ~~>.<~~. I am very sorry, we could not advanced to the World Finals last year. 
When coming into our training room, a lot of books are in my eyes. And every time the books are moving from one place to another one. Now give you the position of the books at the early of the day. And the moving information of the books the day, your work is to tell me how many books are stayed in some rectangles. 
To make the problem easier, we divide the room into different grids and a book can only stayed in one grid. The length and the width of the room are less than 1000. I can move one book from one position to another position, take away one book from a position or bring in one book and put it on one position. 

Input
In the first line of the input file there is an Integer T(1<=T<=10), which means the number of test cases in the input file. Then N test cases are followed. 
For each test case, in the first line there is an Integer Q(1<Q<=100,000), means the queries of the case. Then followed by Q queries. 
There are 4 kind of queries, sum, add, delete and move. 
For example: 
S x1 y1 x2 y2 means you should tell me the total books of the rectangle used (x1,y1)-(x2,y2) as the diagonal, including the two points. 
A x1 y1 n1 means I put n1 books on the position (x1,y1) 
D x1 y1 n1 means I move away n1 books on the position (x1,y1), if less than n1 books at that position, move away all of them. 
M x1 y1 x2 y2 n1 means you move n1 books from (x1,y1) to (x2,y2), if less than n1 books at that position, move away all of them. 
Make sure that at first, there is one book on every grid and 0<=x1,y1,x2,y2<=1000,1<=n1<=100. 

Output
At the beginning of each case, output "Case X:" where X is the index of the test case, then followed by the "S" queries. 
For each "S" query, just print out the total number of books in that area. 

Sample Input
  
2 3 S 1 1 1 1 A 1 1 2 S 1 1 1 1 3 S 1 1 1 1 A 1 1 2 S 1 1 1 2

Sample Output
  
Case 1: 1 3 Case 2: 1 4

解题思路:
二维树状数组的应用。注意下减法和移动的时候,如果要求减去或移动的书数小于n1,那么把现有书全部移走,当前位置为0。这里困惑了好久,详见程序注释部分,后来想到它为什么是错的,因为这是一个树状数组,树状数组存储的不是当前这个位置的数,而是某一连续区间的和,所以要想概率老师讲的那样,按面积来求该位置的值。
这题还有一个比较巧妙的地方,就是题目说初始时每个位置都是1。先把每个位置初始化成0,然后用二维树状数组进行加1操作,比直接每个位置赋为1要好得多。


完整代码:
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <climits>
#include <cassert>
#include <complex>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")typedef long long LL;
typedef double DB;
typedef unsigned uint;
typedef unsigned long long uLL;/** Constant List .. **/ //{const int MOD = int(1e9)+7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const DB EPS = 1e-9;
const DB OO = 1e20;
const DB PI = acos(-1.0); //M_PI;string str;const int maxn = 1003;
int maps[maxn][maxn];int lowbit(int x)
{return x & (-x);
}void add(int x , int y , int d)
{for(int i = x ; i < maxn ; i += lowbit(i)){for(int j = y ; j < maxn ; j += lowbit(j)){maps[i][j] += d;}}
}void init()
{memset(maps , 0 , sizeof(maps));for(int i = 1 ; i < maxn; i ++){for(int j = 1 ; j < maxn ; j ++){add(i , j , 1);}}
}int sum(int x , int y)
{int res = 0;for(int i = x ; i > 0 ; i -= lowbit(i)){for(int j = y ; j > 0 ; j -= lowbit(j)){res += maps[i][j];}}return res;
}int getsum(int x , int y)
{return sum(x + 1 , y + 1) - sum(x , y + 1) - sum(x + 1 , y) + sum(x , y);
}int main()
{#ifdef DoubleQfreopen("in.txt","r",stdin);#endifint T;scanf("%d",&T);int x1 , y1 , x2 , y2 , n1;int cas = 1;while(T--){printf("Case %d:\n",cas++);init();int q;scanf("%d",&q);while(q--){cin >> str;if(str[0] == 'S'){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);if(x1 > x2)swap(x1 , x2);if(y1 > y2)swap(y1 , y2);cout << sum(x2 + 1 , y2 + 1) - sum(x1 , y2 + 1) - sum(x2 + 1 ,y1) + sum(x1 , y1) << endl;}else if(str[0] == 'A'){scanf("%d%d%d",&x1,&y1,&n1);add(x1 + 1 , y1 + 1 , n1);}else if(str[0] == 'D'){scanf("%d%d%d",&x1,&y1,&n1);/*if(maps[x1+1][y1+1] < n1)n1 = maps[x1+1][y1+1];*/int k = getsum(x1 , y1);n1 = min(n1 , k);add(x1 + 1 , y1 + 1 , -n1);}else if(str[0] == 'M'){scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&n1);/*if(maps[x1+1][y1+1] < n1)n1 = maps[x1+1][y1+1];*/int k = getsum(x1 , y1);n1 = min(n1 , k);add(x1 + 1 , y1 + 1 , -n1);add(x2 + 1 , y2 + 1 , n1);}}}
}

 

这篇关于hdu1892(二维树状数组)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146011

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu