牛客第二场-J-farm-二维树状数组

2023-11-11 23:10

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

  二维树状数组真的还挺神奇的,更新也很神奇,比如我要更新一个区域内的和,我们的更新操作是这样的

add(x1,y1,z);
add(x2+1,y2+1,z);
add(x1,y2+1,-z);
add(x2+1,y1,-z);

我们会想为什么和一维的差这么多,我们不妨这样看

add(x1,y1,z);的更新效果

add(x2+1,y2+1,z);的更新效果

那么这个下半区有两个,我们再更新

add(x1,y2+1,-z);的更新效果

add(x2+1,y1,-z);的更新效果

最后用红的去剪掉黄色部分,就是二维数组的区间更新效果

这样就可以区间更新了,并且这样还可以实现区间求和。

回到这道题

我们可以这样实现,把每种花的种类的坐标存下来

再把每种农药撒的对应区间给存下来,并且更新这数状数组区间,即加一(表示这颗花我又撒了一种农药),

最后我们去遍历这种花,把这种农药的影响减去,看这种花是否为0,如果不是0,就表示这颗肯定会死,并且由于我们每次遍历的是同一种的花,所以不存在重复计算(PS:当时我想这种花,被另外的农药浇了3次以上就会在算其他农药的时候重复计算,实际上是没有的,因为我们每次只遍历这种花,这种花遍历后,就不会出现了)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define inf 0x3f3f3f3f
const int MAXN=1e6+9;
using namespace std;
int n,m,q;
struct node{int x1,y1,x2,y2;
};
vector<pair<int,int> >point[MAXN];//存花种类所在的位置
vector<node>p[MAXN];//存询问点
vector<int>tree[MAXN];//
int lowbit(int x){return x&(-x);
}
void add(int x,int y,int z){//二位树状数组的维护//cout<<n<<"--"<<m<<endl;for (int i=x;i<=n;i+=lowbit(i)){for (int j=y;j<=m;j+=lowbit(j)){tree[i][j]+=z;}}
}
void updata(int x1,int y1,int x2,int y2,int z){//二维树状数组的更新操作
  add(x1,y1,z);add(x2+1,y2+1,z);add(x1,y2+1,-z);add(x2+1,y1,-z);
}
int query(int x,int y){int ans=0;for (int i=x;i;i-=lowbit(i)){for(int j=y;j;j-=lowbit(j)){ans+=tree[i][j];}}return ans;
}
int main(){scanf("%d %d %d",&n,&m,&q);for (int i=1;i<=n;i++)tree[i].resize(m+1);//
   for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){int z;scanf("%d",&z);point[z].push_back(make_pair(i,j));//把每个种花对于的坐标存起来
      }}for (int i=1;i<=q;i++){int x1,x2,y1,y2,k;scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&k);updata(x1,y1,x2,y2,1);//更新二维树状数组树p[k].push_back(node{x1,y1,x2,y2});//把这个农药类型的K更改保持起来
   }int ans=0;for (int i=1;i<=n*m;i++){if (point[i].size()>0){for (int j=0;j<p[i].size();j++)updata(p[i][j].x1,p[i][j].y1,p[i][j].x2,p[i][j].y2,-1);//把这种农药的所有更改都删除for (int j=0;j<point[i].size();j++){if (query(point[i][j].first,point[i][j].second))//检查是否含为0,即是否有不是这种类型的更改ans++;}for (int j=0;j<p[i].size();j++)updata(p[i][j].x1,p[i][j].y1,p[i][j].x2,p[i][j].y2,1);//把这种更改删除
      }}printf("%d\n",ans);return 0;
}

 

这篇关于牛客第二场-J-farm-二维树状数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };