题意:给你一个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. python-字符串的处理

    s1 = '###12314##231###' print(s1.split('#')) #split,从左往右遇见# 就拆分一次['', '', '', '12314', '', '231', '' ...

  2. GET和POST是HTTP请求的两种基本方法,区别是什么!?

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

  3. Yii2 kineditor

    用 kineditor实现异步 <table cellspadding=5 width=400> <tr height='150'> <td valign="t ...

  4. BZOJ 3294: [Cqoi2011]放棋子(计数dp)

    传送门 解题思路 设\(f[i][j][k]\)表示前\(k\)个颜色的棋子占领了\(i\)行\(j\)列的方案数,那么转移时可以枚举上一个颜色时占领的位置,\(f[i][j][k]=\sum\lim ...

  5. [CSP-S模拟测试]:小奇挖矿2(DP+赛瓦维斯特定理)

    题目背景 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. 题目描述 现在有$m+1$个星球,从左到右标号为$0$到$n$,小奇最初 ...

  6. mongodbdriver 的C# 驱动findasync变成列表的方法

    IAsyncCursorExtensions.ToList(返回的Task<IAsyncCursor<T>>实例). 也有他的异步版本.可以参见 https://mongodb ...

  7. 106、TensorFlow变量 (二) reshape

    import tensorflow as tf rank_three_tensor = tf.ones([3, 4, 5]) # 创建一个[3,4,5]大小的张量,3行4列,每个位置上有五个元素 ma ...

  8. selenium2-java 浏览器操作常用命令语法

    WebDriver driver = new ChromeDriver(); xpath定位:driver.findElement(By.xpath("//div[@id='register ...

  9. git私有仓库提交代码

    #首次提交 #克隆版本库到本地 git clone http://192.168.3.107:9002/develop/zhong.git cd zhong #创建忽略文件(忽略文件自行编辑) tou ...

  10. NTP时钟调整策略

    一.        问题背景 天威视讯项目3月底发生了一次点播出现节目请求超时的情况,在查询故障的过程中,发现MAP服务器操作系统的时钟被向前调整了11秒,姑且不论是否是这个原因导致的故障,但每台服务 ...