Description

小W 是一片新造公墓的管理人。公墓可以看成一块 \(N×M\) 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地。当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地。为了体 现自己对主的真诚,他们希望自己的墓地拥有着较高的虔诚度。一块墓地的虔诚度是指以这块墓地为中心的十字架的数目。一个十字架可以看成中间是墓地,墓地的 正上、正下、正左、正右都有恰好 $k$ 棵常青树。小W 希望知道他所管理的这片公墓中所有墓地的虔诚度总和是多少

Input

第 一行包含两个用空格分隔的正整数 $N$ 和 $M$,表示公墓的宽和长,因此这个矩形公墓共有$(N+1) ×(M+1)$个格点,左下角的坐标为$(0, 0)$,右上角的坐标为$(N, M)$。第二行包含一个正整数 $W$,表示公墓中常青树的个数。第三行起共 $W$ 行,每行包含两个用空格分隔的非负整数$x_i$和$y_i$,表示一棵常青树的坐标。输入保证没有两棵常青树拥有相同的坐标。最后一行包含一个正整数$k$,意义如题目 所示。

Output

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

HINT

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

所有数据满足$1 \le N, M \le 1,000,000,000$,$0 \le xi \le N$,$0 \le yi \le M$,$1 \le W \le 100,000$,$ 1 \le k \le 10$。

存在$50\%$的数据,满足$1 \le k \le 2$。存在$25\%$的数据,满足$1 \le W \le 10000$。

注意:”恰好有$k$颗树“,这里的恰好不是有且只有,而是从不少于$k$棵的树中恰好选$k$棵

  这道题初看毫无想法……再看仍没有想法……依稀记得以前看过这道题,于是回忆了一下题解,终于知道怎么做了……

  首先,我们可以将坐标离散化(其实只要离散化$x$坐标就够了)。因为所有会产生贡献的墓地上、下、左、右一定都有常青树,因此这些墓地肯定可以由离散化之后的坐标表示。

  然后,我们对每棵常青树$i$求出它的上、下、左、右分别有多少棵常青树(不包括它本身),分别记为$u_i$,$d_i$,$l_i$,$r_i$。这个东西可以将常青树排序后扫一遍求出来。

  接着,我们考虑使用一个扫描线从下往上扫。每到一行,我们可以求一下这一行的墓地会产生多少贡献。即,对于相邻的两棵常青树$i$和$j$($i$在$j$左边),我们设墓地$(i,j)$上方的常青树有$U_{i,j}$棵,下方的常青树有$D_{i,j}$棵,第$i$棵常青树坐标为$x_i,y_j$,那么对答案产生的贡献为:

$$\binom{r_j+1}{k} \binom{l_i+1}{k} \sum_{K=x_i+1}^{x_j-1} \binom{U_{K,y_i}}{k} \binom{D_{K,y_i}}{k}$$

  于是我们现在要考虑的就是如何维护要求和的那个东西。

  一般这种区间和的东西都可以用一个树状数组来维护。像这道题,我们可以将横坐标离散化,然后对横坐标建一个树状数组来维护这个东西。当我们每扫到一棵常青树的时候,就可以把这个横坐标维护的值在树状数组中修改一下即可。区间求和树状数组轻松解决。

  还有一个细节。这道题的模数是$2147483648$,那么我们完全可以使用$unsigned$ $int$来自然溢出,最后再把结果与上$2147483647$即可。

  所以这道题就这么解决了。我的代码还写了一点注释,不懂实现细节的话可以看一下。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010 using namespace std;
typedef unsigned int llg; struct data{
int x,y,b;
}s[maxn];
int n,m,W,wx[maxn],dx[maxn],lx,N,k;
int l[maxn],r[maxn],u[maxn],d[maxn];
llg c[maxn],Cc[maxn][11],ans; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} inline llg C(int x){return Cc[x][k];}//这个函数表示从x个数中去出k个的方案数
bool cmpx(data a,data b){if(a.x==b.x) return a.y<b.y;return a.x<b.x;}
bool cmpy(data a,data b){if(a.y==b.y) return a.x<b.x;return a.y<b.y;}
void add(int x,llg y){while(x<=lx) c[x]+=y,x+=x&(-x);}
llg sum(int x){
llg t=0;
while(x) t+=c[x],x-=x&(-x);
return t;
} void init(){
sort(s+1,s+W+1,cmpx);
for(int i=1;i<=W;i++){
int j=i,now=0;
while(s[j+1].x==s[j].x) j++,d[s[j].b]=++now;
while(i<=j) u[s[i].b]=now--,i++; i--;
N=max(N,d[s[j].b]);
}//求u,d两个数组
sort(s+1,s+W+1,cmpy);
for(int i=1;i<=W;i++){
int j=i,now=0;
while(s[j+1].y==s[j].y) j++,l[s[j].b]=++now;
while(i<=j) r[s[i].b]=now--,i++; i--;
N=max(N,l[s[j].b]);
}//求l,r两个数组
for(int i=0;i<=N;i++) Cc[i][0]=Cc[i][i]=1;
for(int i=2;i<=N;i++)
for(int j=1;j<=k;j++)
Cc[i][j]=Cc[i-1][j-1]+Cc[i-1][j];
} int main(){
File("a");
n=getint()+1; m=getint()+1; W=getint();
for(int i=1;i<=W;i++) dx[++lx]=s[i].x=getint()+1,s[i].y=getint()+1,s[i].b=i;
k=getint(); sort(dx+1,dx+lx+1); lx=unique(dx+1,dx+lx+1)-dx-1; init();
for(int i=1;i<=W;i++) wx[i]=lower_bound(dx+1,dx+lx+1,s[i].x)-dx;//离散化坐标
for(int i=1,j;i<=W;i=j+1){
j=i; add(wx[i],C(d[s[i].b]+1)*C(u[s[i].b])-C(d[s[i].b])*C(u[s[i].b]+1));//修改第i棵常青树对应的树状数组
while(s[j+1].y==s[j].y){
j++; ans+=C(l[s[j-1].b]+1)*C(r[s[j].b]+1)*(sum(wx[j]-1)-sum(wx[j-1]));//统计答案
add(wx[j],C(d[s[j].b]+1)*C(u[s[j].b])-C(d[s[j].b])*C(u[s[j].b]+1));//修改第j棵常青树对应的树状数组
}
}
printf("%d",ans&2147483647);
return 0;
}

BZOJ 1227 【SDOI2009】 虔诚的墓主人的更多相关文章

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

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

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

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

  3. BZOJ 1227 [SDOI2009]虔诚的墓主人 - 扫描线

    Solution 离散化 扫描线, 并用 $rest[i]$ 和 $cnt[i]$ 记录 第$i$列 总共有 $cnt[i]$棵常青树, 还有$rest[i]$ 没有被扫描到. 那么 第$i$ 列的方 ...

  4. 【以前的空间】bzoj 1227 [SDOI2009]虔诚的墓主人

    题解:hzw大神的博客说的很清楚嘛 http://hzwer.com/1941.html 朴素的做法就是每个点如果它不是墓地那么就可形成十字架的数量就是这个c(点左边的树的数量,k)*c(点右边的树的 ...

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

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

  6. bzoj1227 [SDOI2009]虔诚的墓主人(组合公式+离散化+线段树)

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

  7. [BZOJ1227][SDOI2009]虔诚的墓主人 组合数+树状数组

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

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

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

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

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

  10. BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*

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

随机推荐

  1. Maven命令行使用:mvn clean package(打包)

    先把命令行切换到Maven项目的根目录,比如:/d/xxxwork/java/maven-test,然后执行命令:  mvn clean package 执行结果如下: [INFO] Scanning ...

  2. [翻译]用 Puppet 搭建易管理的服务器基础架构(1)

    我通过伯乐在线翻译了一个Puppet简明教程,一共分为四部分,这是第一部分. 原文地址:http://blog.jobbole.com/87679/ 本文由 伯乐在线 - Wing 翻译,黄利民 校稿 ...

  3. spritecow改造

    快速入口 不读文章可以直接拐向这里: spritecow二代:https://kmdjs.github.io/arejs-tool-sprite/ 写在前面 工欲善其事必先利其器,最近fork了一份s ...

  4. Javascript中prototype属性详解

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...

  5. JavaScript数组的reduce方法详解

    数组经常用到的方法有push.join.indexOf.slice等等,但是有一个经常被我们忽略的方法:reduce,这个方法简直强大的不要不要的. 我们先来看看这个方法的官方概述:reduce()  ...

  6. “不要抄代码!自己的代码也不要抄!”

    在 Adventure 位于深圳的电子设备组装厂(SZE)里,小朱狠狠的对自己说. 他刚刚在调试 STM32F407VG 的 SPI 功能.就在昨天,他刚刚调试好了 STM32F407VG 的 USA ...

  7. eclipse — Failed to load the JNI shared library”……\jvm.dll问题原因以及解决方案

    首先上一张出现问题的图片: 出现这个问题一般是你的jdk和eclipse不是同一位的,比如你的jdk是32位的但是eclipse下载的是64位的就会导致这种问题. 解决方案:把两者都换为32或者64位 ...

  8. IOS开发基础知识--碎片14

    1:ZIP文件压缩跟解压,使用ZipArchive 创建/添加一个zip包 ZipArchive* zipFile = [[ZipArchive alloc] init]; //次数得zipfilen ...

  9. php设计模式 原型模式

    原型模式与工程模式作用类似,都是用来创建对象. 与工程模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象.这样就免去了类创建时重复的初始化操作. 原型模式适用于大 ...

  10. nginx File not found

    出现 nginx File not found 错误 首先判断这个文件是否 真的存在 如果文件确实存在 那么应该是 php-fpm 路径有问题了 解决办法 1查看 php-fpm 的配置文件 我的 文 ...