2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]
题目链接:https://www.nowcoder.com/acm/contest/140/J
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
White Cloud wants to help White Rabbit fertilize plants, but the i-th plant can only adapt to the i-th fertilizer. If the j-th fertilizer is applied to the i-th plant (i!=j), the plant will immediately die.
Now White Cloud plans to apply fertilizers T times. In the i-th plan, White Cloud will use k[i]-th fertilizer to fertilize all the plants in a rectangle [x1[i]...x2[i]][y1[i]...y2[i]].
White rabbits wants to know how many plants would eventually die if they were to be fertilized according to the expected schedule of White Cloud.
输入描述:
The first line of input contains 3 integers n,m,T(n*m<=1000000,T<=1000000)
For the next n lines, each line contains m integers in range[1,n*m] denoting the type of plant in each grid.
For the next T lines, the i-th line contains 5 integers x1,y1,x2,y2,k(1<=x1<=x2<=n,1<=y1<=y2<=m,1<=k<=n*m)
输出描述:
Print an integer, denoting the number of plants which would die.
输入
2 2 2
1 2
2 3
1 1 2 2 2
2 1 2 1 1
输出
3
题意:
现有n行m列的矩阵a[1:n][1:m],代表一个农场,
而a[i][j]等于一个整数k,代表这个位置上的农作物是第 k 种,
且第 k 种农作物只能施加第 k 种肥料,施加别的种类肥料会使其死亡,
然后给出T次施肥方案(x1, y1, x2, y2, k),代表对(x1, y1)到(x2, y2)这一块矩阵上所有农作物施加第 k 种肥料,
现在要求知道这T次施肥方案过后,总共死掉了多少格农作物
题解:
先假设我们就用a[i][j]存储了这个格子上的农作物种类,
使用2D-BIT,不难想到,每次施加第 k 种肥,就给这整个矩阵所有格子全加上k,
那么最后我们枚举一遍整个矩阵的所有元素,若某一个元素不能整除a[i][j]就是死掉了,
但是这样一来会出问题,比如第3种农作物上试了一次第1种肥料,又施了一次第2种肥料,那么最后还是能整除3,
这时候需要用随机数哈希,把每个种类编号映射到一个比较大的随机数(大于本题的种类数最大值1e6),这样就能降低上述问题出现概率到一个可以接受的程度。
时间复杂度:预处理哈希$O\left( {nm} \right)$,输入农场$O\left( {nm} \right)$,T次施肥$O\left( {T \cdot \log n \cdot \log m} \right)$,暴力枚举n*m格子查询是否死亡$O\left( {nm \cdot \log n \cdot \log m} \right)$,在nm≤1e6的情况下,$nm \cdot \log n \cdot \log m$不会超过1e8。
(本题使用的是区间修改、单点查询2D-BIT,模板以及详解请传送门:树状数组进阶)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+; struct BIT_2D
{
int n,m;
vector<ll> C[maxn];
int lowbit(int x){return x&(-x);}
void init(int n,int m) //初始化n行m列矩阵
{
this->n=n;
this->m=m;
for(int i=;i<=n;i++)
{
C[i].clear();
for(int j=;j<=m;j++) C[i].push_back();
}
}
void add(int x,int y,ll val)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j)) C[i][j]+=val;
}
void range_add(int x1,int y1,int x2,int y2,ll x) //左上角为(x1,y1)右下角为(x2,y2)的矩阵全部加上x
{
add(x1,y1,x);
add(x1,y2+,-x);
add(x2+,y1,-x);
add(x2+,y2+,x);
}
ll ask(int x,int y) //查询点(x,y)的值
{
ll ret=;
for(int i=x;i>;i-=lowbit(i))
for(int j=y;j>;j-=lowbit(j)) ret+=C[i][j];
return ret;
}
}BIT; int n,m,T;
vector<ll> a[maxn]; ll has[maxn];
inline ll get_rand(int m,int n)
{
return rand()%(n-m+)+m;
}
void myhash(int m)
{
srand(time(NULL));
for(int i=;i<=m;i++) has[i]=get_rand(1e6,9e6);
} int main()
{
scanf("%d%d%d",&n,&m,&T);
myhash(n*m);
BIT.init(n,m);
for(int i=;i<=n;i++)
{
a[i].clear(); a[i].push_back();
for(int j=,type;j<=m;j++)
{
scanf("%d",&type);
a[i].push_back(has[type]);
}
}
for(int i=;i<=T;i++)
{
int x1,y1,x2,y2,k;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
BIT.range_add(x1,y1,x2,y2,has[k]);
} int ans=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(BIT.ask(i,j)%a[i][j] != ) ans++;
}
}
cout<<ans<<endl;
}
注:由于本题n和m给出的范围是n*m≤1e6,显然不能使用1e6*1e6的二维数组,只能用1e6个vector<long long>来代替。
2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]的更多相关文章
- 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)
2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...
- 2018牛客网暑期ACM多校训练营(第一场)D图同构,J
链接:https://www.nowcoder.com/acm/contest/139/D来源:牛客网 同构图:假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所 ...
- 2018 牛客网暑期ACM多校训练营(第一场) E Removal (DP)
Removal 链接:https://ac.nowcoder.com/acm/contest/139/E来源:牛客网 题目描述 Bobo has a sequence of integers s1, ...
- 2018牛客网暑期ACM多校训练营(第十场)A Rikka with Lowbit (树状数组)
链接:https://ac.nowcoder.com/acm/contest/148/A 来源:牛客网 Rikka with Lowbit 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C ...
- 2018牛客网暑期ACM多校训练营(第十场)J Rikka with Nickname(二分,字符串)
链接:https://ac.nowcoder.com/acm/contest/148/J?&headNav=acm 来源:牛客网 Rikka with Nickname 时间限制:C/C++ ...
- 2018牛客网暑期ACM多校训练营(第二场)J Farm(树状数组)
题意 n*m的农场有若干种不同种类作物,如果作物接受了不同种类的肥料就会枯萎.现在进行t次施肥,每次对一个矩形区域施某种类的肥料.问最后枯萎的作物是多少. 分析 作者:xseventh链接:https ...
- 2018牛客网暑期ACM多校训练营(第一场)B Symmetric Matrix(思维+数列递推)
题意 给出一个矩阵,矩阵每行的和必须为2,且是一个主对称矩阵.问你大小为n的这样的合法矩阵有多少个. 分析 作者:美食不可负064链接:https://www.nowcoder.com/discuss ...
- 2018牛客网暑期ACM多校训练营(第五场) F - take - [数学期望][树状数组]
题目链接:https://www.nowcoder.com/acm/contest/143/F 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...
- 2018牛客网暑期ACM多校训练营(第三场) A - PACM Team - [四维01背包][四约束01背包]
题目链接:https://www.nowcoder.com/acm/contest/141/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...
随机推荐
- Linux下修改当前用户的最大线程数和 open files
1 查看当前用户的线程 ulimit -a 2 修改配置文件 vi /etc/security/limits.d/90-nproc.conf 3 改完即可生效 4 修改可打开的最大文件数 vi /e ...
- javascript的replace方法的高级应用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- cocos2d-x 弹出对话框
登陆界面有一点注册按钮,点击之后弹出一个框,让用户输入一些信息; 在网上找的一些方法都是派生一个类,然后自己实现; 我觉得太麻烦了. 我使用分层的方式来显示, 启动界面就一个,背景图片加几个按钮:登陆 ...
- 数组名和数组名取地址&
在C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址. 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是“指向int的常量指针“ ...
- Ruby Tutorial
http://www.tutorialspoint.com/ruby/ruby_quick_guide.htm http://www.cnblogs.com/PurpleCow/archive/201 ...
- Senium 简介
有时候我们在用 requests 抓取页面的时候,得到的结果可能和在浏览器中看到的不一样,在浏览器中可以看到正常显示的页面数据,但是使用 requests 得到的结果并没有.这是因为 requests ...
- iOS - 扩展UIButton的响应区域
扩展UIButton的响应区域 引言 通常在iOS开发中通常会遇到产品说按钮的响应区域不大 而UI给我们的设计是按钮的面积 而不是按钮的响应面积 所以在这种情况下需要我们自己去扩展按钮的响应区域 思考 ...
- iOS - 系统权限(关键时刻很有用的)
iOS开发中权限问题: APP开发避免不开系统权限的问题,如何在APP以更加友好的方式向用户展示系统权限,似乎也是开发过程中值得深思的一件事: 那如何提高APP获取iOS系统权限的通过率呢?有以下几种 ...
- 《转载》WIN10 64位系统 32位Python2.7 PIL安装
http://blog.csdn.net/kanamisama0/article/details/53960281 首先安装这个真的出了好多问题,之前装过一次PIL也失败了,就一直没管,今天刚好找了机 ...
- <转>13个实用的Linux find命令示例
注:本文摘自青崖白鹿,翻译的妈咪,我找到了! -- 15个实用的Linux find命令示例, 感谢翻译的好文. 除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作, ...