Spotlights【思维+前缀和优化】

https://blog.csdn.net/mengxiang000000/article/details/53291883   原博客地址

http://codeforces.com/group/1EzrFFyOc0/contest/738/problem/B  题目链接

题目大意:

给你一个N*M的空间,其中0表示没有人,1表示有人,对应一个好位子以及方向的定义为:

①首先这个位子不能有人。

②其次对应这个位子安排一个照明方向,这个方向上必须有人才行。

让你求一共有多少个这样满足的放置方案。

思路:

1、首先我们O(n*m)暴力枚举出所有的没有人的位子。然后我们如果暴力判断其一行一列的四个方向是否有人的话,时间复杂度会高达:O(n^3)【我们若视n==m的情况下】显然会TLE。

2、那么我们考虑优化:

①设定sum【i】【j】表示第i行,从第一个数加到第j个数的和(前缀和),那么如果我们此时保证(i,j)是没有人的,并且sum【i】【j】>0,那么说明位子(i,j)的左侧有人,那么对应这个位子放置照明方向为左,即是一个可行解。那么同理,如果sum【i】【m】-sum【i】【j】>0,那么说明位子(i,j)的右侧有人,那么对应这个位子放置照明方向为右,即也是一个可行解。

②同理,再设定sum2【i】【j】表示第j列,从第一个数加到第i个数的和,那么同理,如果我们此时保证(i,j)是没有人的,并且sum2【i】【j】>0,那么说明位子(i,j)的上边有人,那么对应这个位子放置照明方向为上,即是一个可行解。那么也是同理,如果sum2【n】【j】-sum2【i】【j】>0,那么说明位子(i,j)的下边有人,那么对应这个位子放置照明方向为下,即也是一个可行解。

③那么此时我们暴力枚举出没有人的位子之后,只需要常数级的操作既可以搞定这个问题了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<set>
 7 #include<vector>
 8 #include<stack>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 #define ll long long
13 #define se second
14 #define fi first
15 const int Mos = 0x7FFFFFFF;  //2147483647
16 const int nMos = 0x80000000;  //-2147483648
17 const int maxn=1e6+5;
18
19 int mp[1005][1005];
20 int sum1[1005][1005],sum2[1005][1005];
21 int n,m,cnt=0;
22
23 int main()
24 {
25     cin>>n>>m;
26     for(int i=1;i<=n;i++)
27         for(int j=1;j<=m;j++)
28         {
29             scanf("%d",&mp[i][j]);
30             sum1[i][j]=mp[i][j]+sum1[i][j-1]; //左到右累加
31             sum2[i][j]=mp[i][j]+sum2[i-1][j]; //上到下累加
32         }
33     for(int i=1;i<=n;i++)
34         for(int j=1;j<=m;j++)
35         {
36             if( mp[i][j] )  continue;
37             if(sum1[i][j]>0)            cnt++; //左边有人
38             if(sum1[i][j]<sum1[i][m])   cnt++; //右边有人
39             if(sum2[i][j]>0)            cnt++; //上边有人
40             if(sum2[i][j]<sum2[n][j])   cnt++; //下边有人
41         }
42
43     cout<<cnt<<endl;
44 }

原文地址:https://www.cnblogs.com/thunder-110/p/9279493.html

时间: 2024-10-11 16:48:28

Spotlights【思维+前缀和优化】的相关文章

bzoj2431: [HAOI2009]逆序对数列(前缀和优化dp)

2431: [HAOI2009]逆序对数列 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2312  Solved: 1330[Submit][Status][Discuss] Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样自然数数列到底有多少个? Input 第一行为两个整数n,k. Ou

Codeforces 712 D. Memory and Scores (DP+滚动数组+前缀和优化)

题目链接:http://codeforces.com/contest/712/problem/D A初始有一个分数a,B初始有一个分数b,有t轮比赛,每次比赛都可以取[-k, k]之间的数,问你最后A比B大的情况有多少种. dpA[i][j]表示第i轮获得j分的情况数.因为第i轮只和第i-1轮有关,所以这里i用滚动数组优化. 要是普通做法3个for就会超时,所以要用前缀和优化,dpA[i][j]可以由一段连续的dp[i - 1][x]转移过来,所以用sumA数组存取dp[i - 1][x]的前缀

[HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

题面: 传送门 有洛谷就尽量放洛谷链接呗,界面友好一点 思路: 和HDU1695比较像,但是这一回有50000组数据,直接莫比乌斯反演慢慢加的话会T 先解决一个前置问题:怎么处理a,c不是1的情况? 很简单,容斥原理搞之 我们设f(x,y)代表gcd(i,j)==e(1<=i<=x,1<=j<=y)的无序数对(i,j)的个数 那么本题答案相当于f(d,b)-f(c-1,b)-f(a-1,d)+f(a-1,c-1) 再来看反演超时的问题 我们注意到原反演过程中,f(1)==mu(i)

[NOI2010][bzoj2005] 能量采集 [欧拉函数+分块前缀和优化]

题面: 传送门 思路: 稍微转化一下,可以发现,每个植物到原点连线上植物的数量,等于gcd(x,y)-1,其中xy是植物的横纵坐标 那么我们实际上就是要求2*sigma(gcd(x,y))-n*m了 又有某不知名神奇定理:一个数的所有因子的phi之和等于这个数本身,其中phi是欧拉函数 因此题目转化为求如下: 我们把式子变个型,就成了如下式子: 然后一个前缀和优化,O(n+sqrt(n))解决 Code: 1 #include<iostream> 2 #include<cstdio>

线性筛素数(欧拉筛)+前缀和优化

关于素数的定义:在大于1的自然数中,除了1和它本身以外不再有其他因数. 判断一个数是否是素数: 1 int x; // 要求的数 2 for(int i=2;i<=sqrt(x);++i) 3 { 4 if(x%i==0) 5 { 6 cout << "这不是素数" << endl; 7 break; 8 } 9 } 埃氏筛法(时间复杂度:$O(NloglogN)$): 1 int num_prime = 0; // 素数的数量 2 int prime[5

P5241 序列(滚动数组+前缀和优化dp)

P5241 序列 挺神仙的一题 看看除了dp好像没什么其他办法了 想着怎么构个具体的图出来,然鹅不太现实. 于是我们想办法用几个参数来表示dp数组 加了几条边肯定要的吧,于是加个参数$i$表示已加了$i$条边 这显然是不够的.于是我们又想:强连通分量.....连通块....... 于是加个$j$表示还有$j$个强连通分量 于是dp数组为$f[i][j]$ 这是我们发现一个问题,状态$f[i][j]$不一定是合法的. 那dp不就GG了吗 再次撕烤,我们发现每次加上的边无非就3种情况: 1.把2个强

HDU-5332(前缀和优化dp/CDQ+NTT)

HDU-5332(CDQ+NTT/前缀和优化dp) 考虑依次求出\(i\)个点的答案 假设当前有\(i-1\)个点,枚举第\(i\)个点前面的点数\(j\),则\(dp_i=dp_{i-j-1}\cdot (j+1)^2\cdot C(i-1,i-j-1)\cdot j!\) 直接转移是\(O(n^2)\)的,可以看到是一个\(dp\)转移与差值有关,所以可以用\(CDQ\)分治+\(NTT\)解决 关于这种简单粗暴的做法,模板题HDU-5730 题解 以下是暴力的代码 #include<bit

4.15 省选模拟赛 编码 trie树 前缀和优化建图 2-sat

好题 np. 对于20分 显然可以爆搜. 对于50分 可以发现每个字符串上的问号要么是0,要么是1.考虑枚举一个字符串当前是0还是1 这会和其他字符串产生矛盾. 所以容易 发现这是一个2-sat问题. 拆点 把任意两个产生矛盾的字符串进行连边.然后最后判矛盾即可. n^2枚举 建图 判断矛盾时使用字符串hash 要分类讨论4种情况. using namespace std; const int MAXN=1010,maxn=500010,cc1=19260817,cc2=114514; int

BNU 13064 Dice (I) 前缀和优化DP

Dice (I) You have N dices; each of them has K faces numbered from 1 to K. Now you have arranged the N dices in a line. You can rotate/flip any dice if you want. How many ways you can set the top faces such that the summation of all the top faces equa