http://www.lydsy.com/JudgeOnline/problem.php?id=1227 (题目链接)

题意

  一个n*m的公墓,一个点上要么是墓地,要么是常青树,给出一个数K,并规定每块墓地的虔诚度是以这个墓地为中心上下左右分别选择K棵常青树的方案数。问整个公墓所有墓地的虔诚度之和。

Solution

  看到棋盘范围大小与点的个数的悬殊差距,首先就想到了离散化,然而离散化之后怎么统计答案呢?

  考虑对于所有点以x轴为第一关键字,y轴为第二关键字进行排序,那么对答案有贡献的墓地坐标一定在已经出现过的x坐标和y坐标中,因为一块有贡献的墓地不可能上下或左右没有常青树。所以我们这里只考虑每次计算一列中的墓地对答案的贡献,然而怎么搞呢。。。

  不会了,请出hzwer:

  先离散横纵坐标

  按照y进行排序,从下往上处理每一行

  l[a],r[a],u[a],d[a]表示一个点上下左右的点数,可以预处理,也可以边做边记录

  如果a,b在同一行,则ans+=c(l[a]+1(包括a),k)*c(r[b]+1,k)再分别乘上ab间的每一个点的c(u[i],k)*c(d[i],k)

  但是这样复杂度为n^2

  于是我们要用树状数组维护a到b所有点的c(u[i],k)*c(d[i],k)之和

  可以这样考虑

  比如某一列某一行有一个点

  在扫描这行之下的时候,这个点是算在u[i]里的,但是扫描这行之上时算在了d[i]中

  于是我们从左往右处理某行的某一个点时,要将树状数组中该点横坐标位置上的数进行修改

  修改的值为就是现在的c(u[i],k)*c[d[i],k]减去原来的,也就是c(u[i],k)*c[d[i],k]-c(u[i]+1,k)*c[d[i]-1,k]

  于是就是树状数组维护一下ok了。

细节

  最后答案要加模再取模,因为可能减成负数。

代码

// bzoj1227
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define MOD 2147483648ll
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=1000010;
struct data {int x,y;}a[maxn];
LL C[maxn][20],c[maxn];
int n,m,W,K,q[maxn],h[maxn],l[maxn],num[maxn]; bool cmp(data a,data b) {
return a.x==b.x ? a.y<b.y : a.x<b.x;
}
void calC() {
for (int i=0;i<=W*2;i++) C[i][0]=1;
for (int i=1;i<=W*2;i++)
for (int j=1;j<=min(i,K);j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
} int lowbit(int x) {
return x&-x;
}
LL query(int x) {
LL s=0;
for (int i=x;i;i-=lowbit(i)) s=(s+c[i])%MOD;
return s;
}
void add(int x,LL val) {
for (int i=x;i<=W*2;i+=lowbit(i)) c[i]=(c[i]+val)%MOD;
} int main() {
scanf("%d%d",&n,&m);
scanf("%d",&W);
for (int i=1;i<=W;i++) {
scanf("%d%d",&a[i].x,&a[i].y);
q[i*2-1]=a[i].x;q[i*2]=a[i].y;
}
scanf("%d",&K);
sort(q+1,q+1+W*2);
int tot=unique(q+1,q+1+W*2)-q-1;
for (int i=1;i<=W;i++) {
a[i].x=lower_bound(q+1,q+1+tot,a[i].x)-q;
a[i].y=lower_bound(q+1,q+1+tot,a[i].y)-q;
h[a[i].y]++;l[a[i].x]++;
}
sort(a+1,a+1+W,cmp);
calC();
LL cnt=0,ans=0;
for (int i=1;i<=W;i++) {
if (i>1 && a[i].x==a[i-1].x) {
cnt++;
LL t1=query(a[i].y-1)-query(a[i-1].y);
LL t2=C[cnt][K]*C[l[a[i].x]-cnt][K]%MOD;
ans=(ans+t1*t2%MOD)%MOD;
}
else cnt=0;
num[a[i].y]++;
LL tmp=C[num[a[i].y]][K]*C[h[a[i].y]-num[a[i].y]][K];
tmp-=C[num[a[i].y]-1][K]*C[h[a[i].y]-num[a[i].y]+1][K];
tmp=(tmp+MOD)%MOD;
add(a[i].y,tmp);
}
printf("%lld",(ans+MOD)%MOD);
return 0;
}

【bzoj1227】 SDOI2009—虔诚的墓主人的更多相关文章

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

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

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

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

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

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

  4. BZOJ1227 [SDOI2009]虔诚的墓主人 【树状数组】

    题目 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地.为 ...

  5. [bzoj1227] [SDOI2009]虔诚的墓主人

    终于填上了这个万年巨坑....从初二的时候就听说过这题...然后一直不敢写QAQ 现在感觉也不是很烦(然而我还是写麻烦了 离散化一波,预处理出组合数什么的.. 要维护对于当前行,每列上方和下方节点凑出 ...

  6. bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)

    传送门 首先,对于每一块墓地,如果上下左右各有$a,b,c,d$棵树,那么总的虔诚度就是$C_k^a*C_k^b*C_k^c*C_k^d$ 那么我们先把所有的点都给离散,然后按$x$为第一关键字,$y ...

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

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

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

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

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

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

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

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

随机推荐

  1. iOS 学习 - 22 异步解析 JSON,使用 FMDB 存储,TableView 显示

    前提是已经知道了有哪些 key 值 Model 类: .h @interface ListModel : NSObject @property (nonatomic, copy)NSString *t ...

  2. routes.rb和link_to的一些规则

    rails文档中描述了一个知识,link_to方法用于产生链接,但链接是根据routes.rb中的路由规则来产生的.这又分为面向资源和非面向资源两种产生链接的方法.比如 routes.rb文件中有两条 ...

  3. CLR线程概览(下)

    作者:施懿民链接:https://zhuanlan.zhihu.com/p/20866017来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 同步: 托管代码 托管代码可 ...

  4. mysql: unknown variable 'character-set-client=utf8'

    在同事安装的MySQL服务器上(居然安装的是My-SQL 5.1.73的老旧版本),登录MySQL时遇到下面"mysql: unknown variable 'character-set-c ...

  5. Linux Bond 技术学习资料

    Bond 技术原理 Bond 就是将多块网卡虚拟成为一块网卡的技术,通过 bond 技术让多块网卡看起来是一个单独的以太网接口设备并具有相同的 IP 地址. Bond 的原理是网卡在混杂 (promi ...

  6. Oracle表的几种连接方式

    1,排序 - - 合并连接(Sort Merge Join, SMJ) 2,嵌套循环(Nested Loops, NL) 3,哈希连接(Hash Join, HJ) Join是一种试图将两个表结合在一 ...

  7. iptables一次性封多个ip,使用ipset 工具

    ipset是什么? ipset是iptables的扩展,它允许你创建 匹配整个地址集合的规则.而不像普通的iptables链只能单IP匹配, ip集合存储在带索引的数据结构中,这种结构即时集合比较大也 ...

  8. Neo4j图数据库管理系统开发笔记之一:Neo4j Java 工具包

    1 应用开发概述 基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发.封装的重点,是解决Neo4j嵌入式版本Emb ...

  9. 教你看懂 OpenStack 日志 - 每天5分钟玩转 OpenStack(29)

    instance 从创建到删除的整个生命周期都是由 Nova 管理的. 后面各小节我们以 instance 生命周期中的不同操作场景为例,详细分析 Nova 不同组件如何协调工作,并通过日志分析加深大 ...

  10. 安卓xml颜色设置

    Android开发中,常常会用到color.xml颜色配置,好的颜色配置可以让尼的应用让人看起来赏心悦目! 不罗嗦,上图先 该工程已经罗列了常用的颜色配置 附上工程链接:http://download ...