首先我们考虑对于一个点,他的十字架的个数是多少,我们用l,r,u,dl,r,u,dl,r,u,d分别表示他左边,右边,上边,下边的树的个数,那么他的贡献应该是
Clk×Crk×Cuk×CdkC_l^k\times C_r^k \times C_u^k \times C_d^kClk×Crk×Cuk×Cdk
但是因为这个n,mn,mn,m都太大了,但是我们发现树的个数只有10510^5105,所以我们可以考虑将他们离散化掉
但是离散化了会不会影响答案呢?显然是不会的,因为如果一行上面没有任何常青树一定不会对答案造成任何的贡献。
接下来我们考虑如果求一字型(在他下面找kkk个,上面找kkk个)的个数应该怎么做
应该是Cuk×CdkC_u^k\times C_d^kCuk×Cdk对吧
那么如果是十字型,就应该是
Cuk×Cdk×val(y)C_u^k\times C_d^k\times val(y)Cuk×Cdk×val(y),val(y)val(y)val(y)表示这一行的贡献
然后我们发现,对于两个点(x,y1),(x,y2)(x,y_1),(x,y_2)(x,y1),(x,y2),对于任意的点(x,y)(x,y)(x,y),如果y∈(y1,y2)y\in(y_1,y_2)y∈(y1,y2),那么他的上下方向上的答案是不变的,那么我们可以利用Cuk×Cdk×∑i=y1+1y2−1val(i)C_u^k\times C_d^k\times \sum_{i=y_1+1}^{y_2-1}val(i)Cuk×Cdk×∑i=y1+1y2−1val(i)快速的算出这一段的答案
那么我们现在要做的是维护一个区间和,我们可以用树状数组来维护
那么d,ud,ud,u怎么求呢?我们可以按xxx为第一关键字,yyy为第二关键字对于每一棵树进行排序,记录sumxisumx_isumxi表示xxx左边为iii的点的个数,ddd可以在循环的过程中预处理出来,而u=sumxi−du=sumx_i-du=sumxi−d
然后考虑更新答案,我们可以记录sumyisumy_isumyi表示yyy左边为iii的点的个数,然后再记录一个visyivisy_ivisyi表示yyy坐标为iii的点已经经过了几次(其实就是lll),然后就可以更新了
总结一下这道题的几个步骤:
- 对于xxx,yyy分别离散化(因为要记录sumxsumxsumx所以xxx坐标离散化也是必须的)
- 按xxx坐标为第一关键字,yyy坐标为第二关键字进行排序
- 利用树状数组维护区间横向一字型的可能情况和
- 扫描每一棵树,记录u,du,du,d算出贡献,同时更新相应的树状数组
我觉得这道题的思考难度主要就在于我们发现离散化之后对答案是 没有影响的
然后后面的都还比较好想吧…
398

被折叠的 条评论
为什么被折叠?



