[BZOJ 2727][HNOI 2012]双十字(树状数组+计数问题)
来源:互联网 发布:小组评比软件 编辑:程序博客网 时间:2024/05/21 06:46
题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2727
思路
这个题好难啊啊啊啊啊啊啊啊啊啊啊啊啊,花了我半天的时间去研究vfk和ydc的题解才算大概搞懂
因为题目描述非常坑爹,竟然没有说
首先预处理出
然后求出
接着我们遍历棋盘中的每个格子
以上各种乱七八糟的东西如下图所示:
考虑假设我们已知点
下面是上面的那个01矩阵中的几个不同的合法的双十字
那么我们看怎么来求这个方案数。。。
假设我们已经知道了下面的横线长度
然后下面的横线长度实际上不是固定的,那么我们需要枚举它,最终的方案数
恩,这时候我们离成功已经非常接近了。。。
看到那个
把上面的式子改一改:
1.
2.
就是个数列求和嘛,(2)是有求和公式的:
2.
代码
代码是扒的ydc的,因为开了内联,所以跑起来比ydc的标程快几百ms
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#define MAXN 2000100#define lowbit(x) ((x)&(-(x)))#define MOD 1000000009using namespace std;typedef long long int LL;int n,m,tot; //tot=0的总数LL bit1[MAXN],bit2[MAXN],bit3[MAXN];LL ans;bool map[MAXN];int L[MAXN],R[MAXN],C[MAXN]; //L[i,j]=(i,j)的左边有多少个连续的1,R[i,j]=(i,j)的右边有多少个连续的1,(i,j)是0的话,L[i,j]=R[i,j]=-1,C[i,j]=min{L[i,j],R[i,j]}int down[MAXN]; //down[i,j]=(i,j)下面有多少个连续的1,(i,j)为0时down[i,j]=-1;int q[MAXN]; //类似于栈的神奇的东西。。。void add(LL sum[],int pos,LL val) //在树状数组sum[]的pos位置加上值val{ while(pos<=m) { sum[pos]=(sum[pos]+val)%MOD; pos+=lowbit(pos); }}LL query(LL sum[],int pos) //查询树状数组sum[]的前pos位置和{ LL ans=0; while(pos>0) { ans=(ans+sum[pos])%MOD; pos-=lowbit(pos); } return ans;}inline int calc(int x,int y) //二维下标(x,y)对应的一位下标{ return (x-1)*m+y;}void prework(){ //预处理L、R、C数组 for(int i=1;i<=n;i++) //枚举第i行 { if(map[calc(i,1)]) L[calc(i,1)]=-1; else L[calc(i,1)]=0; //预处理L[i,1] if(map[calc(i,m)]) R[calc(i,m)]=-1; else R[calc(i,m)]=0; //预处理R[i,m] for(int j=2;j<=m;j++) { if(map[calc(i,j)]) L[calc(i,j)]=-1; else L[calc(i,j)]=L[calc(i,j-1)]+1; } for(int j=m-1;j>=1;j--) { if(map[calc(i,j)]) R[calc(i,j)]=-1; else R[calc(i,j)]=R[calc(i,j+1)]+1; } for(int j=m;j>=1;j--) //????? C[calc(i,j)]=min(L[calc(i,j)],R[calc(i,j)]); } //预处理down数组 for(int j=1;j<=m;j++) //枚举列j { if(map[calc(n,j)]) down[calc(n,j)]=-1; else down[calc(n,j)]=0; //初始化第j列最下面一行(第n行)的值 for(int i=n-1;i>=1;i--) { if(map[calc(i,j)]) down[calc(i,j)]=-1; else down[calc(i,j)]=down[calc(i+1,j)]+1; } }}void clear(int &top,int &tail) //暴力清零{ top=-1; tail=0; for(int i=1;i<=m;i++) bit1[i]=bit2[i]=bit3[i]=0;}void solve() //计数求出答案{ int top=-1,tail=0; //top是从当前格子开始向上延伸的最高点行标,tail是数组q的栈顶指针 for(int j=1;j<=m;j++) //枚举列j { clear(top,tail); for(int i=1;i<=n;i++) //枚举行i { int now=calc(i,j); //now=当前的点在一维数组中的下标 if(map[now]) clear(top,tail); //now是个0,那么和上面1~i-1行的图形连不起来,将top置为-1,tail和数组q置为0 else if(top==-1) top=i; //top为-1,而当前格子为'1',那么top=当前格子高度 else if(C[now]!=0) //now可以构成一条横线,而且它上面有格子当竖线 { LL sum1=query(bit1,C[now])*C[now]%MOD; LL sum2=query(bit2,C[now]); LL sum3=C[now]*(C[now]-1)/2%MOD*(query(bit3,m)-query(bit3,C[now]))%MOD; //sum3是利用了补集转化的思想 LL t=(sum1-sum2+sum3+MOD)%MOD; ans=(ans+t*down[now])%MOD; if(q[tail]==calc(i-1,j)) { int tmp=q[tail],h=(tmp-1)/m+1; //h是now的行标 add(bit1,C[tmp],C[tmp]*(h-top)%MOD); add(bit2,C[tmp],C[tmp]*(C[tmp]+1)/2%MOD*(h-top)%MOD); add(bit3,C[tmp],h-top); } q[++tail]=now; //将点now入队 continue; } if(tail&&q[tail]==calc(i-1,j)) { int tmp=q[tail],h=(tmp-1)/m+1; //h是now的行标 add(bit1,C[tmp],C[tmp]*(h-top)%MOD); add(bit2,C[tmp],C[tmp]*(C[tmp]+1)/2%MOD*(h-top)%MOD); add(bit3,C[tmp],h-top); } } }}int main(){ scanf("%d%d%d",&n,&m,&tot); for(int i=1;i<=tot;i++) { int x,y; scanf("%d%d",&x,&y); map[calc(x,y)]=true; } prework(); solve(); printf("%lld\n",ans); return 0;}
- [BZOJ 2727][HNOI 2012]双十字(树状数组+计数问题)
- [BZOJ 2728][HNOI 2012]与非(并查集+计数问题)
- [BZOJ 2730][HNOI 2012]矿场搭建(Tarjan求割点与桥+计数问题)
- [省选前题目整理][BZOJ 2730][HNOI 2012]矿场搭建(Tarjan求割点+计数问题)
- HNOI2012 双十字 DP+树状数组优化
- BZOJ 2727: [HNOI2012]双十字
- BZOJ 1145 图腾totem [算术计数][树状数组]
- [BZOJ 1196][HNOI 2006]公路修建问题
- BZOJ 2743 HEOI 2012 采花 树状数组
- bzoj 2762 树状数组
- bzoj 3155 树状数组
- bzoj 3594 树状数组
- 排队 [HNOI 2012,Codevs 1994,Bzoj 2729]
- [BZOJ 2731][HNOI 2012]三角形覆盖问题(计算几何+扫描线暴力)
- 【树状数组】bzoj 1452 Count
- BZOJ 3289 莫队 树状数组
- bzoj 1878(离线+树状数组)
- bzoj 1818(树状数组)
- Card Collector - HDU 4336 状压期望dp
- 配置go语言vim
- 智能手机之硬件开发知识篇一
- oracle生成AWR报告
- 2015读书计划
- [BZOJ 2727][HNOI 2012]双十字(树状数组+计数问题)
- 山寨酷狗更换壁纸,图标的颜色也跟着换
- 欢迎使用CSDN-markdown编辑器
- 21天 【健身】
- Scala类型 5: 结构类型
- Android项目Eclipse目录结构
- 自动编译Makefile,原版升级版,支持自动推倒头文件依赖关系、创建目标路径
- BZOJ 3892 [Usaco2014 Dec]Marathon 动态规划
- 自测4. Have Fun with Numbers