Description

在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1-x2|+|y1-y2|。 现在有一个nXn (1<=n<=1000)的矩阵,一开始矩阵中每个元素的值都为零。 对这个矩阵进行m (1<=m<=100000)次操作,每次操作定义如下:
(x1, y1), (x2, y2): 对于矩阵中满足x1<=x<=x2, y1<=y<=y2的所有元素(x, y)加上(x, y)与(x1, y1)的曼哈顿距离|x1-x|+|y1-y|
例如,当n=5,m=2,两组操作分别为(1, 1), (4, 4)和(2, 2), (5, 5):

现在想让你输出m次操作后的矩阵,但是由于本OJ输出文件不能超过1M,所以输出矩阵所有非零元素的乘积即可 (结果对1000000007取余),没有非零项则输出0;

Input

第一行两个整数n, m,分别表示正方形网格的边长和操作次数;
接下来m行,每行4个整数x1 y1 x2 y2;

Output

输出一个整数代表答案。

Sample Input

5 2
1 1 4 4
2 2 5 5

Sample Output

853543927

思路:首先要会差分标记,然后会求前缀和,这里放2个链接

https://blog.csdn.net/k_r_forever/article/details/81775899
https://www.cnblogs.com/OIerShawnZhou/p/7348088.html

然后做的时候建立2个差分数组,一个记录每次要加的最小值,也就是1;一个记录要加的最大值,也就是加到多少为止,为x1+y1那么多。理由我代码里讲。

闲话:这道题可以说是被我和申屠dalao一起玩坏了,先放几张图片


看看这满满一页的提交,看看这内存占用的。。。就快爆128MB了。。。而且我们感觉占用110MB内存和116MB内存的评测速度有天大的差别,所以要压力测试,使劲爆!(这样才会快点#手动滑稽)

代码
先放一份不那么反人类的吧。。。

AC 8776kb 92ms C

#include<stdio.h>
const int mod=1000000007;
int cf[1003][1003];//差分数组一号,记录最小差分值
int cf2[1003][1003];//差分数组二号,记录最大差分值
long long ans=1;
int flag=0;
int main()
{int n,m,a,b,c,d,dif,now;scanf("%d%d",&n,&m);while (m--){scanf("%d%d%d%d",&a,&b,&c,&d);cf[a][b]+=1;cf[c+1][d+1]+=1;cf[a][d+1]-=1;cf[c+1][b]-=1;//二维差分的标记方法,使(a,b)到(c,d)这整块上的值都+1dif=a+b;cf2[a][b]+=dif;cf2[c+1][d+1]+=dif;cf2[a][d+1]-=dif;cf2[c+1][b]-=dif;//使(a,b)到(c,d)这整块上的值都+dif}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){//下面这2个式子其实可以合并到下面那2个for循环里cf[i][j]+=cf[i][j-1]+cf[i-1][j]-cf[i-1][j-1];cf2[i][j]+=cf2[i][j-1]+cf2[i-1][j]-cf2[i-1][j-1];//差分求前缀和的公式,a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+cf[i][j],这里因为a矩阵初始值都是0,而且前缀和只需最后的时候求一遍,所以这题可以直接用cf数组充当a数组来存储前缀和,就相当于cf[i][j]=cf[i][j-1]+cf[i-1][j]-cf[i-1][j-1]+cf[i][j],即上面的式子,省了一些内存。。。}}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){now=cf[i][j]*(i+j)-cf2[i][j];//下面将解释为什么上面的cf2是加上(x1+y1),这里为什么是这样乘起来计算if (now){flag=1;ans=ans*now%mod;}}}if (flag) printf("%lld\n",ans);else printf("0\n");return 0;
}

原因:看下面这图,只需看tot2和sum2。假设他的左上角的点为(a,b),a=1,b=1,假设有一点(x,y),x=3,y=5,注意这里的坐标都是以绝对坐标为准(即以(0,0)点为原点),那么cf[i][j]=1,cf2[i][j]=a+b=2,则cf[i][j] * (i+j) - cf2[i][j] = 1 * (3+5) - (1+1) = 6 = (x-a) + (y-b),[x>a且y>b] ,分配一下就可以看出其实这个式子是会算出(x,y)离(a,b)点多远,相当于题目里的这个|x1-x|+|y1-y|。
好,如果是叠了2层,一样的,那假设有2个左上角的点分别为(a1,b1),(a2,b2),有一点(x,y),那就是cf[i][j] * (i+j) - cf2[i][j] = 2 *(x+y) - (a1+b1+a2+b2) = (x-a1) + (y-b1) + (x-a2) + (y-b2),所以是一样的,没什么区别。。。很easy的道理,而且可以保证的是,如果有cf[i][j]的值那(i,j)的点一定比左上角的(a,b)点大。。。

然后下面是我的反人类代码,使用了快读fread(),原理是把数据先全读到缓冲区,然后再通过字符读取数据

AC 127596kb 48ms C++

#include<stdio.h>
const int mod=1000000007;
int cf[1002][1002];
int cf2[1002][1002];
long long ans=1;
int flag=0;
namespace IO {const int MT = 116 * 1024 * 1024;//这里是116MBchar IO_BUF[MT];int IO_PTR, IO_SZ;void begin() {IO_PTR = 0;IO_SZ = fread (IO_BUF, 1, MT, stdin);}template<typename T>inline bool scan_d (T & t) {while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != '-' && (IO_BUF[IO_PTR] < '0' || IO_BUF[IO_PTR] > '9'))IO_PTR ++;if (IO_PTR >= IO_SZ) return false;bool sgn = false;if (IO_BUF[IO_PTR] == '-') sgn = true, IO_PTR ++;for (t = 0; IO_PTR < IO_SZ && '0' <= IO_BUF[IO_PTR] && IO_BUF[IO_PTR] <= '9'; IO_PTR ++)t = t * 10 + IO_BUF[IO_PTR] - '0';if (sgn) t = -t;return true;}inline bool scan_s (char s[]) {while (IO_PTR < IO_SZ && (IO_BUF[IO_PTR] == ' ' || IO_BUF[IO_PTR] == '\n') ) IO_PTR ++;if (IO_PTR >= IO_SZ) return false;int len = 0;while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != ' ' && IO_BUF[IO_PTR] != '\n')s[len ++] = IO_BUF[IO_PTR], IO_PTR ++;s[len] = '\0';return true;}template<typename T>void print(T x) {static char s[33], *s1; s1 = s;if (!x) *s1++ = '0';if (x < 0) putchar('-'), x = -x;while(x) *s1++ = (x % 10 + '0'), x /= 10;while(s1-- != s) putchar(*s1);}template<typename T>void println(T x) {print(x); putchar('\n');}
};
using namespace IO;//要写上这个
int main()
{begin();//还有这个int n,m,a,b,c,d,dif,now;scan_d(n);scan_d(m);while (m--){scan_d(a);scan_d(b);scan_d(c);scan_d(d);cf[a][b]+=1;cf[c+1][d+1]+=1;cf[a][d+1]-=1;cf[c+1][b]-=1;dif=a+b;cf2[a][b]+=dif;cf2[c+1][d+1]+=dif;cf2[a][d+1]-=dif;cf2[c+1][b]-=dif;}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){cf[i][j]+=cf[i][j-1]+cf[i-1][j]-cf[i-1][j-1];cf2[i][j]+=cf2[i][j-1]+cf2[i-1][j]-cf2[i-1][j-1];}}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){now=cf[i][j]*(i+j)-cf2[i][j];if (now){flag=1;ans=ans*now%mod;}}}if (flag) print(ans);else print(0);return 0;
}

这里还有一份官方的另一份就不放了,x和y两个数组搞来搞去看都看不懂

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
char fre[10] = "data1.in";
char fot[20] = "data1.out";int tot[N][N];
int sum[N][N];
void solve(){int n, m, u, l, d, r;scanf("%d%d", &n, &m);memset(tot, 0, sizeof tot);memset(sum, 0, sizeof sum);for(int i = 1; i <= m; ++i){scanf("%d%d%d%d", &u, &l, &d, &r);sum[u][l] += (u + l);sum[u][r + 1] -= (u + l);sum[d + 1][l] -= (u + l);sum[d + 1][r + 1] += (u + l);tot[u][l] ++;tot[u][r + 1] --;tot[d + 1][l] --;tot[d + 1][r + 1] ++;}for(int i = 1; i <= n; ++i){for(int j = 1; j <= n; ++j){sum[i][j] += sum[i][j - 1];tot[i][j] += tot[i][j - 1];printf("%d ",sum[i][j]);}printf("\n");}for(int i = 1; i <= n; ++i){for(int j = 1; j <= n; ++j){sum[i][j] += sum[i - 1][j];tot[i][j] += tot[i - 1][j];//他这里没有用二维前缀和的公式,而是一步一步求,具体过程可以看上面那张图,我也放在文末了}}LL ans = 1, now = 0;bool flag = false;for(int i = 1; i <= n; ++i){for(int j = 1; j <= n; ++j){now = tot[i][j] * (i + j) - sum[i][j];//printf("%d ",now);
//            sum[i][j] = 0, tot[i][j] = 0;if(now) ans = ans * now % mod, flag = true;}//printf("\n");}if(!flag)   ans = 0;printf("%I64d\n", ans);
}
int main()
{solve();
//    int T = 6;
//    for(int cas = 1; cas <= T; ++cas){
//        fre[4] = ('0' + cas);
//        fot[4] = ('0' + cas);
//        freopen(fre, "r", stdin);
//        freopen(fot, "w", stdout);
//        solve();
//    }return 0;
}
/*
419683495
775697741
996935516
391348459
0
797953655
*/


Excel是个好东西,Excel大法好!!!

[ZSTUOJ4438] 曼哈顿距离相关推荐

  1. 曼哈顿距离和切比雪夫距离链接

    存一下链接慢慢看 曼哈顿距离和切比雪夫距离 这个更清晰一些: 关于曼哈顿距离和切比雪夫距离 NN中常用的距离计算公式:欧式距离.曼哈顿距离.马氏距离.余弦.汉明距离

  2. R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离、dist函数计算矩阵中两两元素的曼哈顿距离

    R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离.dist函数计算矩阵中两两元素的曼哈顿距离 目录 R语言计算曼哈顿距离(Manhattan Distance ...

  3. R语言dist函数距离计算实战(欧几里得距离、曼哈顿距离)

    R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离) 目录 R语言dist函数距离计算实战(欧几里得距离.曼哈顿距离)

  4. 2个点马氏距离计算实例_数据分析基础:距离度量方式(欧式距离、马氏距离、曼哈顿距离)...

    数据分析中,为了评定数据之间的相似度,有很多不同的距离的计算方法,如欧氏距离,马氏距离等等. 欧氏距离 Euclidean distance:欧几里得距离,m维空间中两个点之间的真实距离 离差平方和, ...

  5. 曼哈顿距离,欧式距离,明式距离,切比雪夫距离,汉明距离

    根据我浅薄的知识,以及粗浅的语言,随意总结一下. 1.马氏距离(Manhattan distance),还见到过更加形象的,叫出租车距离的.具体贴一张图,应该就能明白. 上图摘自维基百科,红蓝黄皆为曼 ...

  6. 曼哈顿距离(坐标投影距离之和)d(i,j)=|X1-X2|+|Y1-Y2|.

    曼哈顿距离(坐标投影距离之和)d(i,j)=|X1-X2|+|Y1-Y2|. 我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生 ...

  7. 用曼哈顿距离来巧解---输出菱形的问题

    今天才发现输出菱形有一个特别巧妙的方法.就是用曼哈顿距离. 详细资料可以看这里:曼哈顿距离 那么如何用曼哈顿距离来输出菱形的呢? 我们来分析一下. 你会发现输出 " * " 号的位 ...

  8. 曼哈顿距离java实现_基于javascript实现获取最短路径算法代码实例

    这篇文章主要介绍了基于javascript实现获取最短路径算法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 //A算法 自动寻路 ...

  9. 打印菱形(曼哈顿距离法)

    曼哈顿距离: 我们由定义会发现,距离一个点的曼哈顿距离总是在围绕这个点的一个菱形边上,所以我们就有 默认矩阵行列数是奇数 ceter = int(input()) //中心点的坐标for i in r ...

最新文章

  1. 主成分分析的数学原理
  2. 【NLP】Transformer温故知新
  3. 多线程编程2 - NSOperation
  4. Mongoose Schemas定义中timestamps选项的妙用
  5. 如何实现Oracle数据库之间的数据同步?
  6. 故宫的“烧脑奇书”又火了!豆瓣9.2分,11种结局,可以玩一年!
  7. 阿里巴巴Java开发手册-使用JDK8的Opional类来防止出现NPE问题
  8. 【离散数学】含有两个量词的谓词逻辑公式
  9. 【cocos2d-x从c++到js】10:JS与C++的交互2——JS与C++的“函数重载”问题
  10. [译]C语言实现一个简易的Hash table(5)
  11. 公式推导以及代码书写 11-26
  12. gradle 区分系统_Android 学习记录_系统结构, res 目录, App 目录下的 build.gradle 文件...
  13. c# RestClient 请求接口
  14. excel图表配合下拉菜单_从下拉列表中选择Excel图表日期
  15. 华为手机wifi不显示连接到服务器,华为手机中无法连接WIFI处理方法
  16. 银行合规程序KYC、CDD、AML和TM
  17. 31: Nginx代理服务器 、 Nginx优化 、 总结和答疑
  18. 50 条有趣的 Python 一行代码,建议收藏夹吃灰
  19. 表单提交 onsubmit=return false
  20. ExcelPatternTool: Excel表格-数据库互导工具

热门文章

  1. 一扫天下——ZXing使用全解析
  2. python与seo实战课程百度云,第三期Python与seo实战课程已上传到B站
  3. 使用代理IP的注意事项
  4. 问题解决:Word在插入图片后保存变模糊
  5. Ulink2 与 Jlink
  6. tcp的三次握手和四次挥手(详解+图片)
  7. MOOC网神经网络与深度学习TensorFlow实践1——TensorFlow简介、python语言基础
  8. HR经理应该掌握的5个原则
  9. android动画--小飞机旋转效果
  10. 深入Java自动化探针技术的原理和实践