题目描述

在C 部落,双十字是非常重要的一个部落标志。所谓双十字,如下面两个例子,由两条水平的和一条竖直的”1“线段组成,要求满足以下几个限制: ![] 我们可以找到 5 个满足条件的双十字,分别如下:  注意最终的结果可能很大,只要求输出双十字的个数 mod 1,000,000,009 的值·两条水平的线段不能在相邻的两行。·竖直线段上端必须严格高于两条水平线段,下端必须严格低于两条水平线段。 ·竖直线段必须将两条水平线段严格划分成相等的两半。·上方的水平线段必须严格短于下方的水平线段。 所以上面右边的例子是满足要求的最小的双十字。现在给定一个 R*C的01 矩阵,要求计算出这个 01 矩阵中有多少个双十字。例如下面这个例子,R=6,C=8,01 矩阵如下:

输入输出格式

输入格式:

第一行为用空格隔开的两个正整数 R和C,分别表示01矩阵的行数和列数。输入文件第二行是一个非负整数N,表示01矩阵中”0“的个数。接下来的N行,每行为用空格隔开的两个正整数x和y(1<=x<=R,1<=y<=C),表示(x,y)是一个”0“。数据保证N个”0“的坐标两两不同。数据保证R,C,N<=10,000,R*C<=1,000,000.(事实上R*C可能稍大于原设定)

输出格式:

D mod 1,000,000,009 的结果,其中D 为要求的 01矩阵中双十字的个数。

输入输出样例

输入样例#1: 复制

6  8
12
1 2
1 3
1 4
1 6
2 2
3 2
3 3
3 4
3 7
6 4
6 6
4 8
输出样例#1: 复制
5
因为10000×10000存不下,所以用编号代替坐标
首先DP求出L,R,U,D数组表示左右上下有多少个连续的1
一个点左右可拓展的长度应当是min(L,R)
枚举十字架中心在第几列
当了某一行,考虑以它作于下面一个横线的方案数
$\sum_{len=1}^{L[i]} min(L[j], len-1)×D[i]×(j-top)$
把min拆掉:
1.当len-1<=L[j],则$\sum_{len=1}^{L[i]} L[j]×D[i]×(j-top)$
2.当len-1>L[j],则$\sum_{len=1}^{L[i]} (len-1)×D[i]×(j-top)$
可以变成:
1.当L[j]<=L[i],贡献$(L[i]-(L[j]+1)/2)×D[i]×(j-top)×L[j]$
2.当L[j]>L[i],贡献$L[i]×(L[i]-1)/2×D[i]×(j-top)$
维护3个树状数组,分别维护:
$(j-top)$
$(j-top)*L[j]$
$(j-top)*L[j]*L[j]$
每一次碰到0或算完一列的答案要给树状数组清0
因为十字架上面的横线不能是i-1,所以考虑先算完i,再加入i-1
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int mp[],U[],D[],L[],R[],n,r,c;
int Mod=1e9+,f1[],f2[],f3[],inv2,top,ans,ed;
int get_id(int x,int y)
{
return c*(x-)+y;
}
int qpow(int x,int y)
{
int res=;
while (y)
{
if (y&) res=1ll*res*x%Mod;
x=1ll*x*x%Mod;
y>>=;
}
return res;
}
void add1(int x,int d,int N)
{
if (x==) return;
while (x<=N)
{
f1[x]+=d;
if (f1[x]>=Mod) f1[x]-=Mod;
x+=x&(-x);
}
}
void add2(int x,int d,int N)
{
if (x==) return;
while (x<=N)
{
f2[x]+=d;
if (f2[x]>=Mod) f2[x]-=Mod;
x+=x&(-x);
}
}
void add3(int x,int d,int N)
{
if (x==) return;
while (x<=N)
{
f3[x]+=d;
if (f3[x]>=Mod) f3[x]-=Mod;
x+=x&(-x);
}
}
int query1(int x)
{
int s=;
while (x)
{
s+=f1[x];
if (s>=Mod) s-=Mod;
x-=(x&(-x));
}
return s;
}
int query2(int x)
{
int s=;
while (x)
{
s+=f2[x];
if (s>=Mod) s-=Mod;
x-=(x&(-x));
}
return s;
}
int query3(int x)
{
int s=;
while (x)
{
s+=f3[x];
if (s>=Mod) s-=Mod;
x-=(x&(-x));
}
return s;
}
int get_van(int x,int y,int N)
{
int t=L[get_id(x,y)];
int as=;
int s2=query2(t),s3=query3(t);
as=(1ll*t*s2%Mod-1ll*(s3+s2)%Mod*inv2%Mod+Mod);
if (as>=Mod) as-=Mod;
int s1=(query1(N)-query1(t)+Mod);
if (s1>=Mod) s1-=Mod;
as=(as+1ll*t*(t-)%Mod*inv2%Mod*s1%Mod);
if (as>=Mod) as-=Mod;
return 1ll*as*D[get_id(x,y)]%Mod;
}
void update(int x,int y,int N)
{
int t=L[get_id(x,y)];
add1(t,x-top,N);
add2(t,1ll*(x-top)*t%Mod,N);
add3(t,1ll*(x-top)*t%Mod*t%Mod,N);
}
int main()
{int i,j,x,y,l;
cin>>r>>c;
cin>>n;
inv2=qpow(,Mod-);
memset(mp,-,sizeof(mp));
for (i=;i<=n;i++)
{
scanf("%d%d",&x,&y);
mp[get_id(x,y)]=;
}
for (i=;i<=r;i++)
{
for (j=;j<=c;j++)
  {
  if (mp[get_id(i,j)]==-)
  mp[get_id(i,j)]=;
  }
}
for (i=;i<=r;i++)
{
L[get_id(i,)]=;
for (j=;j<=c;j++)
if (mp[get_id(i,j-)]==&&mp[get_id(i,j)]==) L[get_id(i,j)]=L[get_id(i,j-)]+;
else L[get_id(i,j)]=;
R[get_id(i,c)]=;
for (j=c-;j>=;j--)
if (mp[get_id(i,j+)]==&&mp[get_id(i,j)]==) R[get_id(i,j)]=R[get_id(i,j+)]+;
else R[get_id(i,j)]=;
for (j=;j<=c;j++)
  L[get_id(i,j)]=min(L[get_id(i,j)],R[get_id(i,j)]);
}
for (j=;j<=c;j++)
{
U[get_id(,j)]=;
for (i=;i<=r;i++)
  if (mp[get_id(i-,j)]==&&mp[get_id(i,j)]==) U[get_id(i,j)]=U[get_id(i-,j)]+;
  else U[get_id(i,j)]=;
D[get_id(r,j)]=;
for (i=r-;i>=;i--)
if (mp[get_id(i+,j)]==&&mp[get_id(i,j)]==) D[get_id(i,j)]=D[get_id(i+,j)]+;
else D[get_id(i,j)]=;
}
for (j=;j<=c;j++)
{top=;
ed=min(c-j,j-);
for (l=;l<=ed;l++)
f1[l]=f2[l]=f3[l]=;
for (i=;i<=r;i++)
  {
  if (top==&&mp[get_id(i,j)]==) top=i;
  if (mp[get_id(i,j)]==&&top)
  {
  for (l=;l<=ed;l++)
  f1[l]=f2[l]=f3[l]=;
  top=;
  continue;
  }
  if (top==) continue;
  if (i==top) continue;
  if (i-top>=&&L[get_id(i,j)]>)
  {
  ans=ans+get_van(i,j,ed);
  if (ans>=Mod) ans-=Mod;
  }
  if (i-!=top&&L[get_id(i-,j)]>)
  update(i-,j,ed);
  }
}
cout<<ans;
}

[HNOI2012]双十字的更多相关文章

  1. bzoj 2727: [HNOI2012]双十字

    Description 在C 部落,双十字是非常重要的一个部落标志.所谓双十字,如下面两个例子,由两条水平的和一条竖直的"1"线段组成,要求满足以下几个限制: 我们可以找到 5 个 ...

  2. [BZOJ2727][HNOI2012]双十字

    bzoj luogu sol 先预处理从每个点出发向上/下/左/右能延伸多长. 考虑怎么计算答案.我们只要枚举中轴线,再枚举上方的十字交点,枚举下方的十字交点,然后算答案即可. 考虑一个左右宽的最小值 ...

  3. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  4. #YCB#待做题目与填坑资料

    各种填坑资料(qwq) 主席树(by YL)戳 树套树(by ZSY)戳 不要问我这些题咋来的(查大佬的水表呗) 题目列表: [HDU5977]Garden of Eden [BZOJ2752][HA ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. bzoj 2729: [HNOI2012]排队

    2729: [HNOI2012]排队 Time Limit: 10 Sec Memory Limit: 128 MB Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体 ...

  7. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  8. bzoj 2734: [HNOI2012]集合选数 状压DP

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 321[Submit][Status ...

  9. bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status ...

随机推荐

  1. Alpha冲刺——Day1

    一.合照 二.项目燃尽图 三.项目进展 1.界面设计:图形界面部分完成 2.数据库设计:数据库设计基本完成 3.搭建基本服务器框架 github链接 四.明日规划 1.继续完成剩下的图形界面 2.An ...

  2. Beta冲刺第七天

    一.昨天的困难 没有困难. 二.今天进度 1.林洋洋:MD图片上传,修复权限问题,修复本地存储判空问题,修复协作申请没有过滤问题. 2.黄腾达:添加文件链接和邀请链接复制功能,协作树界面优化. 3.张 ...

  3. Beta版本敏捷冲刺每日报告——Day2

    1.情况简述 Beta阶段第二次Scrum Meeting 敏捷开发起止时间 2017.11.3 08:00 -- 2017.11.3 22:00 讨论时间地点 2017.11.3晚9:00,软工所实 ...

  4. Java课程设计报告——学生成绩管理系统

    一.需求分析 1.数据存储在数据库和文件中 2.分为"教师"模块和"学生"模块. 3.学生模块提供登陆功能,登陆成功后可查询数学.Java.体育成绩 (学生学号 ...

  5. 第四十四条:为所有导出的API元素编写文档注释

    简而言之,要为API编写文档,文档注释是最好,最有效的途径.对于所有可导出的API元素来说,使用文档注释应该被看作是强制性的.要 采用一致的风格来遵循标准的约定.记住,在文档注释内部出现任何的HTML ...

  6. 搭建java环境——使用Sublime Text 3(windows环境)

    实现sublime Text 3对Java编译执行 参考网址:http://tieba.baidu.com/p/2609515186 1.1直接在安装路径下找到*\Packages\Java.subl ...

  7. win10 安装mingw ruby rails

    原文可以参考 https://ruby-china.org/topics/17581 在window10 安装ruby rails https://rubyinstaller.org/download ...

  8. Java中Math类的常用方法

    public class MathDemo { public static void main(String args[]){ /** * abs求绝对值 */ System.out.println( ...

  9. Golang学习--开篇

    最近开始接收一个新项目,是使用Golang写的,需要重新捡起Golang来,于是就有了这个系列博客. Golang的环境配置,我就不说了,让我们直接开始. Golang官网:https://golan ...

  10. 我自己总结的C#开发命名规范整理了一份

    我自己总结的C#开发命名规范整理了一份 标签: 开发规范文档标准语言 2014-06-27 22:58 3165人阅读 评论(1) 收藏 举报  分类: C#(39)  版权声明:本文为博主原创文章, ...