题目链接

分析 :

最简单的想法当然就是去模拟

直接对每个施肥料的操作进行模拟、然后计算贡献

但是这显然会超时、这题需要换一个思维

对于一个土地(也就是二维平面上的一个点)的种类是 T'

如果它被操作了 K1 次、那么如果我能知道所有用 T' 施肥的操作

对这块土地施肥的次数 K2、那么当 K1 == K2 的时候、这片土地就不会 Die

而当 K1 != K2 的时候、则这块土地就会 Die 、换句话说就是答案要加一

计算每个土地被操作的总次数

要知道每个土地被操作了多少次、可以利用二维前缀和的方式来计算贡献

假设操作矩形的左上角和右下角分别为 (x1, y1) 、(x2, y2)

那么可以用二维数组模拟这个矩形的四个顶点分别做加减操作

具体的就是 arr[x1][y1]++、arr[x1][y2+1]--、arr[x2+1][y1]--、arr[x2][y2]++

然后 N*M 地去遍历整个土地、利用这条式子 arr[i][j] += arr[i-1][j] + arr[i][j-1] - arr[i-1][j-1]

最后 arr 这个二维数组中所有的数字表示的即为某一块土地被操作的总次数

计算被用于操作的肥料对其施肥的土地操作的总次数

如果仔细思考一下便会发现这个是一个很经典的二维偏序问题

如果你解决过类似 CDQ 分治的题目、那么这个便会很容易理解

对于每个种类的肥料、其可能被用于若干次施肥操作

施肥操作是一个矩形、可以将矩形操作分解成四个点的加减操作

也就是将一个操作变成四个操作、如果你熟悉 CDQ 分治、那么这个会好理解

可以发现对于每一个点、在二维平面上只有其左上角的操作点对它有影响

所以每次处理都将所有操作对于 X 轴先进行排序、然后利用树状数组维护 Y 轴

还有一开始的原矩形元素也应该被视作操作、保存到分治数组里面去、用于问询

可能很乱,看代码就清楚了

(最好是你先去熟悉偏序问题和CDQ分治、因为代码的很多细节都是套路操作、不赘述了)

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define ULL unsigned long long
  4.  
  5. #define scl(i) scanf("%lld", &i)
  6. #define scll(i, j) scanf("%lld %lld", &i, &j)
  7. #define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
  8. #define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)
  9.  
  10. #define scs(i) scanf("%s", i)
  11. #define sci(i) scanf("%d", &i)
  12. #define scd(i) scanf("%lf", &i)
  13. #define scIl(i) scanf("%I64d", &i)
  14. #define scii(i, j) scanf("%d %d", &i, &j)
  15. #define scdd(i, j) scanf("%lf %lf", &i, &j)
  16. #define scIll(i, j) scanf("%I64d %I64d", &i, &j)
  17. #define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
  18. #define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
  19. #define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
  20. #define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
  21. #define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
  22. #define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)
  23.  
  24. #define lson l, m, rt<<1
  25. #define rson m+1, r, rt<<1|1
  26. #define lowbit(i) (i & (-i))
  27. #define mem(i, j) memset(i, j, sizeof(i))
  28.  
  29. #define fir first
  30. #define sec second
  31. #define VI vector<int>
  32. #define ins(i) insert(i)
  33. #define pb(i) push_back(i)
  34. #define pii pair<int, int>
  35. #define VL vector<long long>
  36. #define mk(i, j) make_pair(i, j)
  37. #define all(i) i.begin(), i.end()
  38. #define pll pair<long long, long long>
  39.  
  40. #define _TIME 0
  41. #define _INPUT 0
  42. #define _OUTPUT 0
  43. clock_t START, END;
  44. void __stTIME();
  45. void __enTIME();
  46. void __IOPUT();
  47. using namespace std;
  48. ;
  49.  
  50. struct ARR{
  51. int r, c, op;
  52. ARR(){};
  53. ARR(int _r, int _c, int _o):r(_r), c(_c), op(_o){};
  54. bool operator < (const ARR & rhs) const{
  55. if(r == rhs.r && c == rhs.c) return abs(op) > abs(rhs.op);
  56. if(r == rhs.r) return c < rhs.c;
  57. return r < rhs.r;
  58. }
  59. }; vector<ARR> arr[maxn];
  60.  
  61. int n, m, T;
  62. ];
  63. int Bit[maxn];
  64.  
  65. inline void BitAdd(int i, int val)
  66. {
  67. while(i <= m){
  68. Bit[i] += val;
  69. i += (i & (-i));
  70. }
  71. }
  72.  
  73. int BitSum(int i)
  74. {
  75. ) ;
  76. ;
  77. ){
  78. ret += Bit[i];
  79. i -= (i & (-i));
  80. }return ret;
  81. }
  82.  
  83. void BitClean(int i)
  84. {
  85. while(i <= m){
  86. Bit[i] = ;
  87. i += (i & (-i));
  88. }
  89. }
  90.  
  91. int idx(int r, int c)
  92. { return r * m + c; }
  93.  
  94. int main(void){__stTIME();__IOPUT();
  95.  
  96. sciii(n, m, T);
  97.  
  98. ; i<=n; i++)
  99. ; j<=m; j++){
  100. int tmp; sci(tmp);
  101. arr[tmp].pb(ARR(i, j, ));
  102. }
  103.  
  104. ; i<T; i++){
  105. int x1, y1, x2, y2, k;
  106. sciiii(x1, y1, x2, y2); sci(k);
  107. arr[k].pb(ARR(x1, y1, ));
  108. arr[k].pb(ARR(x1, y2+, -));
  109. arr[k].pb(ARR(x2+, y1, -));
  110. arr[k].pb(ARR(x2+, y2+, ));
  111. Cnt[idx(x1, y1)]++;
  112. Cnt[idx(x1, y2+)]--;
  113. Cnt[idx(x2+, y1)]--;
  114. Cnt[idx(x2+, y2+)]++;
  115. }
  116.  
  117. ; i<=n; i++)
  118. ; j<=m; j++)
  119. Cnt[idx(i, j)] += Cnt[idx(i-, j)] +
  120. Cnt[idx(i, j-)] -
  121. Cnt[idx(i-, j-)];
  122.  
  123. // for(int i=1; i<=n; i++,puts(""))
  124. // for(int j=1; j<=m; j++)
  125. // printf("%d ", Cnt[idx(i, j)]);
  126.  
  127. ;
  128. ; i<=n*m; i++){
  129. sort(all(arr[i]));
  130. //printf("----- %d ------\n", i);
  131. ; j<(int)arr[i].size(); j++){
  132. //printf("$$=> %d %d %d\n", arr[i][j].r, arr[i][j].c, arr[i][j].op);
  133. ){
  134. if(Cnt[idx(arr[i][j].r, arr[i][j].c)] != BitSum(arr[i][j].c))
  135. ans++;
  136. }else BitAdd(arr[i][j].c, arr[i][j].op);
  137. }
  138. ; j<(int)arr[i].size(); j++){
  139. )
  140. BitClean(arr[i][j].c);
  141. }
  142. }
  143.  
  144. printf("%d\n", ans);
  145.  
  146. __enTIME();;}
  147.  
  148. void __stTIME()
  149. {
  150. #if _TIME
  151. START = clock();
  152. #endif
  153. }
  154.  
  155. void __enTIME()
  156. {
  157. #if _TIME
  158. END = clock();
  159. cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
  160. #endif
  161. }
  162.  
  163. void __IOPUT()
  164. {
  165. #if _INPUT
  166. freopen("in.txt", "r", stdin);
  167. #endif
  168. #if _OUTPUT
  169. freopen("out.txt", "w", stdout);
  170. #endif
  171. }

Nowcoder farm ( 树状数组、二维前缀和、二维偏序 )的更多相关文章

  1. HDU 5465——Clarke and puzzle——————【树状数组BIT维护前缀和+Nim博弈】

    Clarke and puzzle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  2. [POI2005]AUT-The Bus 树状数组维护最大前缀和

    #include<cstdio> #include<algorithm> using namespace std; const int N=100000+3; int x[N] ...

  3. [POI2007]MEG-Megalopolis 树状数组 + dfs序前缀和 好题

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const ...

  4. HH的项链 树状数组动态维护前缀

    #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const ...

  5. 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?

    开心.jpg J.farm 先解释一下题意,题意就是一个n*m的矩形区域,每个点代表一个植物,然后不同的植物对应不同的适合的肥料k,如果植物被撒上不适合的肥料就会死掉.然后题目将每个点适合的肥料种类( ...

  6. 【二维树状数组】【CF10D】 LCIS

    传送门 Description 给你两个串,求他们的最长公共上升子序列 Input 第一行是第一个串的长度\(n\) 第二行\(n\)个数代表第一个串 第三行是第二个串的长度\(m\) 第四行\(m\ ...

  7. 二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟

    P4514 上帝造题的七分钟 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了00的n×mn×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b)(a,b),右下 ...

  8. POJ_2155 Matrix 【二维树状数组】

    一.题面 POJ2155 二.分析 楼教主出的题,是二维树状数组非常好的题,还结合了开关问题(开关变化的次数如果为偶数,状态不变,奇数状态相反). 题意就是给了一个二维的坐标平面,每个点初始值都是0, ...

  9. 1042.D Petya and Array 前缀 + 树状数组

    11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...

随机推荐

  1. Oracle块,区,段

    数据块(Block) 数据块Block是Oracle存储数据信息的最小单位.注意,这里说的是Oracle环境下的最小单位.Oracle也就是通过数据块来屏蔽不同操作系统存储结构的差异.无论是Windo ...

  2. C++多线程基础学习笔记(三)

    一.detach()大坑 上一篇随笔(二)中提到detach()是用来分离主线程和子线程的,那么需要考虑一个问题,就是如果主线程跑完了,主线程中定义的变量就会被销毁(释放内存),这时回收变量仍作为参数 ...

  3. layui自定义插件citySelect 省市区三级联动选择

    省市区三级菜单联动插件 citySelect.js /** * @ name : citySelect 省市区三级选择模块 * @ Author: aggerChen * @ version: 1.0 ...

  4. 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt

    第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...

  5. JS图片轮播[左右轮播

    直接可以用,网上摘下来的! <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http ...

  6. AGC009E Eternal Average

    atc 神题orz 那个擦掉\(k\)个数然后写上一个平均值可以看成是\(k\)叉Huffman树的构造过程,每次选\(k\)个点合成一个新点,然后权值设为平均值.这些0和1都会在叶子的位置,同时每个 ...

  7. loj 2392「JOISC 2017 Day 1」烟花棒

    loj 答案显然满足二分性,先二分一个速度\(v\) 然后显然所有没有点火的都会往中间点火的人方向走,并且如果两个人相遇不会马上点火,要等到火快熄灭的时候才点火,所以这两个人之后应该在一起行动.另外有 ...

  8. yii自定义验证

    自定义验证类 class BaseModel extends Model { public function rules() { return [ ['obj', ContentSecurityVal ...

  9. 让图表的Y轴 产生几个刻度距离

    动态设置max 查看官网 写入方法 获取到你数据最大值 然后+个100

  10. jQuery 遍历 - 后代

    向下遍历 DOM 树 下面是两个用于向下遍历 DOM 树的 jQuery 方法: children() find() jQuery children() 方法 children() 方法返回被选元素的 ...