问题描述

小W是一片新造公墓的管理人。公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地。

当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地。为了体现自己对主的真诚,他们希望自己的墓地拥有着较高的虔诚度。

一块墓地的虔诚度是指以这块墓地为中心的十字架的数目。一个十字架可以看成中间是墓地,墓地的正上、正下、正左、正右都有恰好k棵常青树。

小W希望知道他所管理的这片公墓中所有墓地的虔诚度总和是多少。

输入格式

输入文件religious.in的第一行包含两个用空格分隔的正整数N和M,表示公墓的宽和长,因此这个矩形公墓共有(N+1) ×(M+1)个格点,左下角的坐标为(0, 0),右上角的坐标为(N, M)。

第二行包含一个正整数W,表示公墓中常青树的个数。

第三行起共W行,每行包含两个用空格分隔的非负整数xi和yi,表示一棵常青树的坐标。输入保证没有两棵常青树拥有相同的坐标。

最后一行包含一个正整数k,意义如题目所示。

输出格式

输出文件religious.out仅包含一个非负整数,表示这片公墓中所有墓地的虔诚度总和。为了方便起见,答案对2,147,483,648取模。

样例输入

5 6

13

0 2

0 3

1 2

1 3

2 0

2 1

2 4

2 5

2 6

3 2

3 3

4 3

5 2

2

样例输出

6

说明

图中,以墓地(2, 2)和(2, 3)为中心的十字架各有3个,即它们的虔诚度均为3。其他墓

地的虔诚度为0。

对于30%的数据,满足1 ≤ N, M ≤ 1,000。

对于60%的数据,满足1 ≤ N, M ≤ 1,000,000。

对于100%的数据,满足1 ≤ N, M ≤ 1,000,000,000,0 ≤ xi ≤ N,0 ≤ yi ≤ M,1 ≤ W ≤ 100,000,1 ≤ k ≤ 10。

存在50%的数据,满足1 ≤ k ≤ 2。

存在25%的数据,满足1 ≤ W ≤ 10000。

解析

设点A上面有a棵树,下面有b棵树,左边有c棵树,右边有d棵树。那么,点A的虔诚度为

\[C_a^k*C_b^k*C_c^k*C_d^k
\]

在纵坐标相同的两棵树之间,所有墓地的左右数量不变,因此这些墓地的虔诚度之和就是左右的组合数的乘积再乘上每一列的组合数乘积之和。我们有如下做法:将每棵树按照纵坐标从小到大排序,纵坐标相同按横坐标从小到大排序。用树状数组维护每一列上的组合数乘积,即\(C_a^k+C_b^k\)。每次扫描一行,在两个相邻的树之间统计答案,用区间求和即可实现。每扫描一行后更新树状数组中的值。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
#define N 2000002
using namespace std;
const int mod=2147483648;
struct node{
int x,y;
}a[N];
int n,m,w,t,i,j,k,vx[N],vy[N],c[N],sum[N],num[N],f[N][12],n1,n2;
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
int my_comp(const node &a,const node &b)
{
if(a.y==b.y) return a.x<b.x;
return a.y<b.y;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
for(int i=x;i<=n1;i+=lowbit(i)) c[i]=(c[i]+y+mod)%mod;
}
int ask(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i)) ans=(ans+c[i]+mod)%mod;
return ans;
}
signed main()
{
n=read();m=read();w=read();
for(i=1;i<=w;i++){
a[i].x=read(),a[i].y=read();
vx[i]=a[i].x;
vy[i]=a[i].y;
}
t=read();
f[0][0]=1;
for(i=1;i<=w;i++){
f[i][0]=1;
for(j=1;j<=t;j++) f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
}
sort(vx+1,vx+w+1);
sort(vy+1,vy+w+1);
sort(a+1,a+w+1,my_comp);
n1=unique(vx+1,vx+w+1)-vx-1;
n2=unique(vy+1,vy+w+1)-vy-1;
for(i=1;i<=w;i++){
a[i].x=lower_bound(vx+1,vx+n1+1,a[i].x)-vx;
a[i].y=lower_bound(vy+1,vy+n2+1,a[i].y)-vy;
sum[a[i].x]++;
}
i=j=1;
int ans=0;
while(i<=w){
while(a[i].y==a[j].y) j++;
int cnt=j-i,now=1;
for(k=i+1;k<j;k++,now++){
int l=a[k-1].x,r=a[k].x;
ans=(ans+(ask(r-1)-ask(l)+mod)%mod*f[now][t]%mod*f[cnt-now][t]%mod)%mod;
}
for(k=i;k<j;k++){
int p=a[k].x;
add(p,-f[num[p]][t]*f[sum[p]-num[p]][t]%mod);
num[p]++;
add(p,f[num[p]][t]*f[sum[p]-num[p]][t]%mod);
}
i=j;
}
printf("%lld\n",(ans%mod+mod)%mod);
return 0;
}

[洛谷P2154] SDOI2009 虔诚的墓主人的更多相关文章

  1. BZOJ1227或洛谷2154 [SDOI2009]虔诚的墓主人

    BZOJ原题链接 洛谷原题链接 又是扫描线,题解可看大佬的博客(太懒了不想打) #include<cstdio> #include<algorithm> using names ...

  2. bzoj1227 P2154 [SDOI2009]虔诚的墓主人

    P2154 [SDOI2009]虔诚的墓主人 组合数学+离散化+树状数组 先看题,结合样例分析,易得每个墓地的虔诚度=C(正左几棵,k)*C(正右几棵,k)*C(正上几棵,k)*C(正下几棵,k),如 ...

  3. P2154 [SDOI2009]虔诚的墓主人 树状数组

    https://www.luogu.org/problemnew/show/P2154 题意 在一个坐标系中,有w(1e5)个点,这个图中空点的权值是正上,正下,正左,正右各取k个的排列组合情况.计算 ...

  4. P2154 [SDOI2009]虔诚的墓主人

    略有一点点思维的题. 首先,如果一个点上,下,左,右分别有\(a,b,c,d\)棵树,那这个点的十字架方案为\(C_{a}^{k}C_{b}^{k}C_{c}^{k}C_{d}^{k}\). 按x坐标 ...

  5. luogu P2154 [SDOI2009]虔诚的墓主人

    luogu 下面记一个点上下左右点数分别为\(u_i,d_i,l_i,r_i\) 枚举每个中间点太慢了,考虑枚举两个点之间横的一条线段,这里面的点左边点数目都相同,右边点数目都相同,然后只要查一下区间 ...

  6. 【BZOJ1227】[SDOI2009]虔诚的墓主人(线段树)

    [BZOJ1227][SDOI2009]虔诚的墓主人(线段树) 题面 BZOJ 洛谷 题解 显然发现答案就是对于每一个空位置,考虑上下左右各有多少棵树,然后就是这四个方向上树的数量中选\(K\)棵出来 ...

  7. 【LG2154】[SDOI2009]虔诚的墓主人

    [LG2154][SDOI2009]虔诚的墓主人 题面 洛谷 题解 如果您没有看懂题,请反复阅读题面及样例 可以发现,对于某一个点,它的答案就是上下左右几个组合数乘起来. 这样直接做复杂度显然爆炸,考 ...

  8. BZOJ 1227: [SDOI2009]虔诚的墓主人

    1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec  Memory Limit: 259 MBSubmit: 1078  Solved: 510[Submit][Stat ...

  9. Bzoj 1227: [SDOI2009]虔诚的墓主人 树状数组,离散化,组合数学

    1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec  Memory Limit: 259 MBSubmit: 895  Solved: 422[Submit][Statu ...

随机推荐

  1. between()函数

    1 between函数返回一个布尔量,即如果在该范围内,返回True,否则返回False. 注意between()中括号内是左闭右闭区间 在dataframe中常可用来通过选择某一列元素的范围来选择另 ...

  2. Jvm组成以及调优

    Jvm的内存由三部分组成Eden,S0,S1,Old以及Metaspace(JDK1.8之前的Perm区)五部分组成: (图片摘自VisualVM的Visual GC插件) 抽象为三代:新生代(Ede ...

  3. cross appdomain access

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. mysql数据库自带数据库介绍

    show databases:查看mysql自带数据库有information_schema,mysql, performance_schema, test information_schema数据库 ...

  5. [转帖]mysql数据库主从配置

    mysql数据库主从配置 https://www.toutiao.com/i6680489302947791371/ 多做实验 其实挺简单的 很多东西 要提高自信 去折腾. 架构与我 2019-04- ...

  6. OpenGL字体绘制

    /* glfont.hpp sdragonx 2019-08-15 00:03:33 opengl字体类,提供初学者参考学习 opengl初始化之后,创建字体 font.init(L"微软雅 ...

  7. [LeetCode] 164. 最大间距

    题目链接 : https://leetcode-cn.com/problems/maximum-gap/ 题目描述: 给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值. 如果数组元素个数 ...

  8. 分布式事务解决方案汇总:2PC、3PC、消息中间件、TCC、状态机+重试+幂等(转)

    数据一致性问题非常多样,下面举一些常见例子.比如在更新数据的时候,先更新了数据库,后更新了缓存,一旦缓存更新失败,此时数据库和缓存数据会不一致.反过来,如果先更新缓存,再更新数据库,一旦缓存更新成功, ...

  9. Delphi XE2_XE3 Update

    Delphi 和 C++Builder XE2 更新摘要 XE2的关键特性如下: 1. FireMonkey Application Platform支持运行在Windows (32和64位),Mac ...

  10. Red Hat Enterprise Linux查看系统版本命令

    # arch 返回结果为i686表示32位系统,x86_64表示64位系统. # uname -a # uname -r # lsb_release -a # cat /proc/version # ...