题意:给你一个01矩阵,问此矩阵有多少个和恰好为k的子矩形。

思路:分治,对于当前矩形,用一条中线把矩形分成两半,分治之后计算跨过中线的矩形个数。更具体的来说(假设划了一条水平中线),我们枚举矩形左右边界,然后用指针维护一下到中线的连续和为k的边界。之后通过差分就可以计算出对应的左右边界的矩形的贡献数目。对于一个n * m的矩阵,计算贡献的时间复杂度是O(n * (m * k + n))的,带有n * n项,所以计算的时候需要用交替画水平线和竖直线,不然就超时了。总复杂度O(n * m * k * ( log(n) + log(m) ) );

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2510;
int sum[maxn][maxn];
char s[maxn][maxn];
int n, m, K;
long long ans;
int p1[10], p2[10];
int cal(int x1, int y1, int x2, int y2) {
return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
}
void div(int x1, int y1, int x2, int y2, bool flag) {
if(x1 > x2 || y1 > y2) return;
if(x1 == x2 && y1 == y2) {
ans += (cal(x1, y1, x2, y2) == K);
return;
}
if(flag) {
int mid = (x1 + x2) >> 1;
div(x1, y1, mid, y2, !flag);
div(mid + 1, y1, x2, y2, !flag);
for (int i = y1; i <= y2; i++) {
for (int k = 0; k <= K; k++) {
p1[k] = mid, p2[k] = mid + 1;
}
for (int j = y2; j >= i; j--) {
for (int k = 0; k <= K; k++) {
while(p1[k] >= x1 && cal(p1[k], i, mid, j) <= k) p1[k]--;
while(p2[k] <= x2 && cal(mid + 1, i, p2[k], j) <= k) p2[k]++;
}
for (int k = 1; k < K; k++) {
ans += (p1[k - 1] - p1[k]) * (p2[K - k] - p2[K - k - 1]);
}
if(K > 0) {
ans += (mid - p1[0]) * (p2[K] - p2[K - 1]);
ans += (p2[0] - mid - 1) * (p1[K - 1] - p1[K]);
} else if(K == 0) {
ans += (mid - p1[0]) * (p2[0] - mid - 1);
}
}
}
}
else {
int mid = (y1 + y2) >> 1;
div(x1, y1, x2, mid, !flag);
div(x1, mid + 1, x2, y2, !flag);
for (int i = x1; i <= x2; i++) {
for (int k = 0; k <= K; k++) {
p1[k] = mid, p2[k] = mid + 1;
}
for (int j = x2; j >= i; j--) {
for (int k = 0; k <= K; k++) {
while(p1[k] >= y1 && cal(i, p1[k], j, mid) <= k) p1[k]--;
while(p2[k] <= y2 && cal(i, mid + 1, j, p2[k]) <= k) p2[k]++;
}
for (int k = 1; k < K; k++) {
ans += (p1[k - 1] - p1[k]) * (p2[K - k] - p2[K - k - 1]);
}
if(K > 0) {
ans += (mid - p1[0]) * (p2[K] - p2[K - 1]);
ans += (p2[0] - mid - 1) * (p1[K - 1] - p1[K]);
} else if(K == 0) {
ans += (mid - p1[0]) * (p2[0] - mid - 1);
}
//printf("%d %d %d %d %d %d\n", x1, y1, x2, y2, 2, ans);
}
}
}
}
int main() {
//freopen("out.txt", "r", stdin);
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + (s[i][j] == '1');
}
div(1, 1, n, m, 0);
printf("%lld\n", ans);
}

  

Codeforces 364E 分治的更多相关文章

  1. Pudding Monsters CodeForces - 526F (分治, 双指针)

    大意: n*n棋盘, n个点有怪兽, 求有多少边长为k的正方形内恰好有k只怪兽, 输出k=1,...,n时的答案和. 等价于给定n排列, 对于任意一个长为$k$的区间, 若最大值最小值的差恰好为k, ...

  2. A Story of One Country (Hard) CodeForces - 1181E2 (分治)

    大意: 给定$n$个平面上互不相交的矩形. 若一个矩形区域只包含一个矩形或者它可以水平或垂直切成两块好的区域, 那么这个矩形区域是好的. 求判断整个平面区域是否是好的. 分治判断, 可以用链表实现删除 ...

  3. Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]

    洛谷 Codeforces 根号分治真是妙啊. 思路 考虑对于单独的一个\(k\)如何计算答案. 与"赛道修建"非常相似,但那题要求边,这题要求点,所以更加简单. 在每一个点贪心地 ...

  4. Codeforces Round #190 (Div. 2) E. Ciel the Commander 点分治

    E. Ciel the Commander Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.codeforces.com/contest ...

  5. CodeForces 553E Kyoya and Train 动态规划 多项式 FFT 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8847145.html 题目传送门 - CodeForces 553E 题意 一个有$n$个节点$m$条边的有向图 ...

  6. CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8835443.html 题目传送门 - CodeForces 958F3 题意 有$n$个球,球有$m$种颜色,分 ...

  7. codeforces 161D Distance in Tree 树上点分治

    链接:https://codeforces.com/contest/161/problem/D 题意:给一个树,求距离恰好为$k$的点对是多少 题解:对于一个树,距离为$k$的点对要么经过根节点,要么 ...

  8. Codeforces 833D Red-Black Cobweb [点分治]

    洛谷 Codeforces 思路 看到树上路径的统计,容易想到点分治. 虽然只有一个限制,但这个限制比较麻烦,我们把它拆成两个. 设黑边有\(a\)条,白边有\(b\)条,那么有 \[ 2a\geq ...

  9. Codeforces 1093E Intersection of Permutations [CDQ分治]

    洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...

随机推荐

  1. pychrome激活

    http://blog.csdn.net/fx677588/article/details/58164902

  2. Java二级练习试题一

    为保护本地主机,对Applet安全限制中正确的是() A. Applet可加载本地库或方法 B. Applet可读.写本地计算机的文件系统 C. Applet可向Applet之外的任何主机建立网络连接 ...

  3. Gitbook环境搭建及制作——2019年10月24日

    1.gitbook介绍 GitBook 是一个基于 Node.js 的命令行工具,支持 Markdown 和 AsciiDoc 两种语法格式,可以输出 HTML.PDF.eBook 等格式的电子书.可 ...

  4. 【Elasticsearch】ElasticSearch基本查询

    学习elasticsearch查询用法的时候,发现这篇文章写得很详细,为以后方便查看,就直接搬过来了,原文链接在下面. 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附 ...

  5. vue数据渲染、条件判断及列表循环

    1.数据渲染  {{msg}} <template> <div id="app"> {{msg}} </div> </template&g ...

  6. LintCode之删除排序链表中的重复元素

    题目描述: 我的代码: /** * Definition for ListNode * public class ListNode { * int val; * ListNode next; * Li ...

  7. JS获取浏览器地址栏的多参数值的任意值

    常用的几个方法就不讲了,这里我用的是两个方法组 使用方法是: getParamValue("id"); http://localhost:2426/TransactionNotes ...

  8. Java 反射简介(转载)

    反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...

  9. How to show out three rows from the same databand On A4?

    How to show out three rows from the same databand On A4? Quote Post by DoraHuang » Tue Mar 13, 2018 ...

  10. 关于JS读取DOM对象(标签)的自定义属性

    DOM对象对于js来说,是个很基础的元素,我们写js一般来说,都一定会对它进行操作.我们可以很方便地给它加上自定义的属性,比如: var test = document.getElementById( ...