[SDOI2009] 虔诚的墓主人

首先我们考虑对于一个点,他的十字架的个数是多少,我们用 l , r , u , d l,r,u,d l,r,u,d分别表示他左边,右边,上边,下边的树的个数,那么他的贡献应该是
C l k × C r k × C u k × C d k C_l^k\times C_r^k \times C_u^k \times C_d^k Clk×Crk×Cuk×Cdk
但是因为这个 n , m n,m n,m都太大了,但是我们发现树的个数只有 1 0 5 10^5 105,所以我们可以考虑将他们离散化掉
但是离散化了会不会影响答案呢?显然是不会的,因为如果一行上面没有任何常青树一定不会对答案造成任何的贡献。


接下来我们考虑如果求一字型(在他下面找 k k k个,上面找 k k k个)的个数应该怎么做
应该是 C u k × C d k C_u^k\times C_d^k Cuk×Cdk对吧
那么如果是十字型,就应该是
C u k × C d k × v a l ( y ) C_u^k\times C_d^k\times val(y) Cuk×Cdk×val(y), v a l ( y ) val(y) val(y)表示这一行的贡献
然后我们发现,对于两个点 ( x , y 1 ) , ( x , y 2 ) (x,y_1),(x,y_2) (x,y1),(x,y2),对于任意的点 ( x , y ) (x,y) (x,y),如果 y ∈ ( y 1 , y 2 ) y\in(y_1,y_2) y(y1,y2),那么他的上下方向上的答案是不变的,那么我们可以利用 C u k × C d k × ∑ i = y 1 + 1 y 2 − 1 v a l ( i ) C_u^k\times C_d^k\times \sum_{i=y_1+1}^{y_2-1}val(i) Cuk×Cdk×i=y1+1y21val(i)快速的算出这一段的答案
那么我们现在要做的是维护一个区间和,我们可以用树状数组来维护
那么 d , u d,u d,u怎么求呢?我们可以按 x x x为第一关键字, y y y为第二关键字对于每一棵树进行排序,记录 s u m x i sumx_i sumxi表示 x x x左边为 i i i的点的个数, d d d可以在循环的过程中预处理出来,而 u = s u m x i − d u=sumx_i-d u=sumxid
然后考虑更新答案,我们可以记录 s u m y i sumy_i sumyi表示 y y y左边为 i i i的点的个数,然后再记录一个 v i s y i visy_i visyi表示 y y y坐标为 i i i的点已经经过了几次(其实就是 l l l),然后就可以更新了


总结一下这道题的几个步骤:

  • 对于 x x x, y y y分别离散化(因为要记录 s u m x sumx sumx所以 x x x坐标离散化也是必须的)
  • x x x坐标为第一关键字, y y y坐标为第二关键字进行排序
  • 利用树状数组维护区间横向一字型的可能情况
  • 扫描每一棵树,记录 u , d u,d u,d算出贡献,同时更新相应的树状数组

我觉得这道题的思考难度主要就在于我们发现离散化之后对答案是 没有影响的
然后后面的都还比较好想吧…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值