鸣谢:140142耐心讲解缕清了我的思路
题意:由于调这道题调的头昏脑涨,所以题意自己搜吧,懒得说。
方法:离线+树状数组+离散化
解析:首先深表本??对出题人的敬(bi)意(shi)。这道题简直丧心病狂,看完题后大脑一片空白,整个人都不好了,刚开始的思路是什么呢?暴力思想枚举每个墓碑,然后计算每个墓碑的虔诚度,然后再来统计。不过看看数据范围呢?10^9*10^9的矩阵,最多才10^5个树,光枚举就已经超时了,所以肯定不行。(不过要是考试真没思路我就那么搞了- -!)
然后也想到来枚举墓碑,不过还是些许犹豫,毕竟偏差较大,写的话实现难。然后我就不知道怎么搞了。
今天140142神?耐心的给我讲了大体的思路。
就是呢,把所有的点按x从大到小,x相同y从大到小排序,然后呢一个个来枚举。

用如上的图来说。
先明确树状数组在本题是如何体现的。
首先这个树状数组存的值是什么?
c[u[i]][K]?c[d[i]][K]
其中,c是组合数,u[i]是对于i这个总坐标,当前的上面的树的个数,d代表向下求。
现在这些点的顺序应该已经排好了,那么我来模拟一下正解的过程。
显然第一个遍历的点应该是[0,3]。
这时候我们能做什么呢? 统计他的左边有多少点,右边有多少点,当然,把他归到左边。为什么?因为我们是从左到右处理,所以后面假设这一排还有点的话,[0,3]这个点当然在左边。
统计完左右后,我们还能维护当前的上下,道理差不多吧。
经过很多的实验,个人认为统计这些点上下左右最好用map来搞,非常实用。
以上就是第一个遍历过程。
接下来,到[1,3]这个点,此时呢,这个点又到了新的一排,所以左右的话应该重新维护一下,而上下呢?显然只是上–,下++。但是这时候就要注意了。在对上下进行操作之前,当前的树状数组显然存的是[0,3]时候的值,所以我们要进行更新。而怎么更新呢?
因为现在树状数组存的是
c[u[3]][K]?c[d[3]][K]
,
而我们要将之更新成
c[u[3]?1][K]?c[d[3]+1][K]
,也就是对应着上–,下++。为什么要这么做呢?
让我们接着遍历。
[3,0]这个点同样换行了,所以维护左右,上下也填到树状数组。
[3,1]这个店没有换行,所以左++,右–,上下填到树状数组。
**
关键就是到了[3,5]这个点。
**
我们可以看出,此时他与[3,1]之间是有3个点满足题意的。那我们就要把这三个点的值加到答案上(其实[3,1]时也有这个过程,只不过它与上一个点紧挨着,所以不可能有解,被我跳过了)而这个加的值应该是什么?
(∑i=24c[u[i]][K]?c[d[i]][K])?c[l[5?1]][K]?c[r[5?1]][K]
所以说,树状数组的作用就是维护这段区间的
c[u[i]][k]?c[d[i]][k]
的和的,只不过是多了动态更新,也就是每个点过后,都要重新更新树状数组的值。
树状数组的用法就说完了,如果没懂,亦或是看看别人的题解,亦或是请教请教AC的人,亦或是理解理解上面这个求和公式。
接下来
图中我特意留了几个空行,我们发现,2,4,7这三列并没有什么卵用,完全可以删除掉,不过这个删除是必须的,因为10^9的边长的矩形,咱们只算其中10^5个点,光是内存就开不下,所以离散化一下列,也就是纵坐标是必然的。
后记:我太弱
#include
#include