CF 372B Counting Rectangles is Fun [dp+数据维护]

题意,给出一个n行m列的矩阵

里面元素是0或者1

给出q个询问

a,b,c,d

求(a,b)到(c,d)有多少个由0组成的矩形

我们定义

即为求(a,b)到(c,d)有多少个由0组成的矩形

对一个矩形来说

dp[a][b][c][d]=dp[a][b][c][d-1]+dp[a][b][c-1][d]-dp[a][b][c-1][d-1]+包含右下角(当前点)的矩形;

重点就在包含右下角(当前点c,d)的矩形,如何计算这个

我们可以暴力扫描,需要nm的复杂度,乘上原有复杂度,,已经会超过时限

也可以用一个VECTOR来记录1的位置,对我们扫描到的行,二分查找G[该行]中1的位置(在第b列到第d列间第一个1),然后根据相对位置再来计算,最坏查找次复杂度为

也可以状压整张图

我们要知道的是b列到d列中1的情况,我们把代表该行状态的数s先左位移再右位移到只剩b列到d列的状态

然后作运算s&(-s)返回第一个1的位置比如,如果s是0101000,则返回8

为什么能这样?来看下是怎么回事

还是以s=0101000为例

负数即正数的补码,-s即是1010111+1=1011000

0101000

1011000 &

0001000

但是这里

会返回2^40

但是没关系,我们对返回的数模997(经测验没有地址冲突)

这样就可以把它丢到表里

vis[2^1]=1

vis[2^2]=2

vis[2^3]=3

...

vis[2^40]=40

这样就可以得到当前行中b到d列里从右往左第一个1的相对于第d列的位置

算下复杂度,全是几个O(1)的操作,大致为O(1)

说下我觉得最厉害最省事的方法

CF上最短size的代码

是这么做的

记录每个格子距离上一个1的距离d[i][j]

在找包含右下角(当前点c,d)的矩形的时候,我们取adder=min(记录数d[i][d],adder)(adder一开始是d-b+1),每次加上这个adder,从c行到a行(d[c][d]~d[a][d]),一直维护这个adder

O(1)且非常方便

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
int g[55][55];
int num[55][55];
int dp[55][55][55][55];
int main(){
#ifndef ONLINE_JUDGE
	freopen("/home/rainto96/in.txt","r",stdin);
#endif

	int n,m,q;
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			scanf("%1d",&g[i][j]);
			num[i][j]=num[i][j-1]+1;
			if(g[i][j]==1)
				num[i][j]=0;
		}
	for(int a=1;a<=n;a++)
		for(int b=1;b<=m;b++)
			for(int c=a;c<=n;c++)
				for(int d=b;d<=m;d++){
					int& now=dp[a][b][c][d]=dp[a][b][c][d-1]+dp[a][b][c-1][d]-dp[a][b][c-1][d-1];
					int add=d-b+1;
					for(int i=c;i>=a;i--){
						add=min(add,num[i][d]);
						now+=add;
					}
				}
	for(int i=1;i<=q;i++){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		cout<<dp[a][b][c][d]<<endl;
	}
}
时间: 2024-07-30 00:25:51

CF 372B Counting Rectangles is Fun [dp+数据维护]的相关文章

Codeforces 372B. Counting Rectangles is Fun【动态规划,暴力枚举】(lowbit()小用法)

题目大意: 给出一个由0,1构成的矩阵,询问(a,b)到(c,d)两个点之间的只含有0的矩形有多少个. 方法: 由于矩阵不大,最多40*40,而且询问量很大(10^5)由此我们考虑o(1)输出答案,首先用一个四维数组预处理出答案,最后直接输出即可. 令dp[a][b][c][d]为(a,b)到(c,d)两个点之间的只含有0的矩形的数量, 则递推的公式: dp[a][b][c][d]=dp[a][b][c][d-1]+dp[a][b][c-1][d]-dp[a][b][c-1][d-1] 每次计算

Codeforces 372B Counting Rectangles is Fun

http://codeforces.com/problemset/problem/372/B 题意:每次给出一个区间,求里面有多少个矩形 思路:预处理,sum[i][j][k][l]代表以k,l为右下角,左上角不超过i,j有多少矩形,然后询问的时候枚举右下角就可以了 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iost

Project Euler 85 :Counting rectangles 数长方形

Counting rectangles By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles: Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the

ZOJ (狗狗)1426 Counting Rectangles(暴力)

Counting Rectangles Time Limit: 2 Seconds      Memory Limit: 65536 KB We are given a figure consisting of only horizontal and vertical line segments. Our goal is to count the number of all different rectangles formed by these segments. As an example,

UVA - 10574 Counting Rectangles

Description Problem H Counting Rectangles Input: Standard Input Output:Standard Output Time Limit: 3Seconds   Given n points on the XY plane, count how many regular rectanglesare formed. A rectangle is regular if and only if its sides are all paralle

CF 366C Dima and Salad [天平DP]

题目大意:n个水果,水果有甜度和卡路里两个属性,选择一些水果,使得甜度之和与卡路里之和比例为k,并且使得甜度之和最大 我们可以定义二维dp,dp[当前游标扫到的个数][平衡度]=当前平衡度下最大的ai和,平衡度定义为ai-bi*k,很巧秒的定义方式,可以节省一维时空. 注意到平衡度可正可负(范围在-10000到10000) 我们可以定义如下 int m[1111][22222] int *d[i]=&m[i][10000] dp[num+1][balance]=max(self,dp[num][

UVA 10574 - Counting Rectangles(枚举+计数)

10574 - Counting Rectangles 题目链接 题意:给定一些点,求能够成几个矩形 思路:先把点按x排序,再按y排序,然后用O(n^2)的方法找出每条垂直x轴的边,保存这些边两点的y坐标y1, y2.之后把这些边按y1排序,再按y2排序,用O(n)的方法找出有几个连续的y1, y2都相等,那么这些边两两是能构成矩形的,为C2cnt种,然后累加起来就是答案 代码: #include <stdio.h> #include <string.h> #include <

一致性哈希服务器的数据维护

本文是实例说明一致性哈希服务器的数据维护用途.理论说明参考:http://blog.csdn.net/chenjiayi_yun/article/details/41624603 如下图所示,本例中一致性哈希服务器群组是视频服务器群组,包括三类服务器:VChannelMediaServer.VChannelServer.VChannelLoadServer.VChannelSuperServer. VChannelMediaServer频道动态数据(成员数据)和接入服务器,保存频道成员信息,提供

SD从零开始51-54 信用控制范围, 信用范围数据维护, 自动信用控制, 信用控制-阻止后续功能

[原创] SD从零开始51 信用控制范围 分散的组织结构Decentralized Organization 信用控制范围是一个为客户指定和控制信用限额的组织单元: 依赖于你公司的需求,应收款可以使用集中的或者分散的信用政策来管理: 使用分散的信用政策,每个公司代码可以为它的客户确定它自己的信用数据: 一个销售组织只可以分配给一个公司代码,一个业务交易只可以分配给一个信用控制范围: 集中的组织结构Centralized Organization 在集中的组织结构中,公司代码组合到信用管理的一个信