洛谷题目页面传送门 & CodeForces题目页面传送门

题意见洛谷里的翻译。(注意翻译里有错误,应该是优先选上面的矩阵,在同一行的优先选左边的矩阵)

这题一看就会做啊

(以下设大矩阵是\(n\times m\),小矩阵是\(n0\times m0\),第\(i\)行第\(j\)列高度为\(a_{i,j}\))

不难想到可以预处理出二维前缀和数组\(Sum\),后面就可以\(\mathrm{O}(1)\)求出一个小矩阵的和;然后跑\(2\)遍单调队列,第\(1\)次求出\(\forall i\in[1,n],\forall j\in[1,m-m0+1],mn1_{i,j}=\min\limits_{k=j}^{j+m0-1}\{a_{i,k}\}\),第二次求出\(\forall i\in[1,n-n0+1],\forall j\in[1,m-m0+1],mn2_{i,j}=\min\limits_{k=i}^{k+n0-1}\left\{\min\limits_{o=j}^{j+m0-1}\{a_{k,o}\}\right\}=\min\limits_{k=i}^{k+n0-1}\{mn1_{k,j}\}\)。那么一个左上角在\((i,j)\)的小矩阵的花费显然是\(Sum_{i+n0-1,j+m0-1}-Sum_{i-1,j+m0-1}-Sum_{i+n0-1,j-1}+Sum_{i-1,j-1}-n0\times m0\times mn2_{i,j}\)了。然后把所有小矩阵排个序,从头到尾扫一遍,如果一个小矩阵中有已经被标记的格子了,就不选;否则就选,并且把它所覆盖的格子都标记一下。但这样会TLE。不难想到,判一个小矩阵有没有被标记过的格子,只需要判四个角就可以了,这样判的时间总共就是\(\mathrm{O}(nm)\)了;而每个格子最多会被标记一次,所以标记总共也是\(\mathrm{O}(nm)\),这样就不会TLE了。(或者你用树状数组、线段树或其他一些更高级的数据结构我也不拦你)

对了,这题非常的卡常。我第一次交,T了。然后加了个快读,还是T了。然后把所有int改成register int,还是T了。最后我发现,原来计算一个小矩阵的花费虽然\(\mathrm{O}(1)\),但是常数略大,而我却把它放在sortcmp里计算,等于在扩大计算花费的常数(众所周知,快排里一个元素可能和多个元素比较)。于是我事先计算所有小矩阵的花费,然后存下来,cmp的时候直接调用,然后就AC了。

下面贴上蒟蒻又长又丑的代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. #define pb push_back
  5. #define mp make_pair
  6. #define X first
  7. #define Y second
  8. #define ri register int//呵呵
  9. void read(int &x){//快读
  10. x=0;char c=getchar();
  11. while(!isdigit(c))c=getchar();
  12. while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
  13. }
  14. const int N=1000,M=1000;
  15. int n,m/*大矩阵的尺寸*/,n0,m0/*小矩阵的尺寸*/;
  16. int a[N+1][M+1];//高度
  17. int Sum[N+1][M+1];//二维前缀和
  18. int q[N],head,tail;//单调队列
  19. int mn1[N+1][M+1]/*一维最小值*/,mn2[N+1][M+1]/*二维最小值*/;
  20. vector<pair<int,int> > ord;//小矩阵访问顺序
  21. int cst[N+1][M+1];//小矩阵的花费
  22. int calc_cst(int x,int y){//计算左上角在(x,y)的小矩阵的花费
  23. return Sum[x+n0-1][y+m0-1]-Sum[x-1][y+m0-1]-Sum[x+n0-1][y-1]+Sum[x-1][y-1]-n0*m0*mn2[x][y];
  24. }
  25. bool cmp(pair<int,int> x,pair<int,int> y){//排序方式,以花费为第一关键字从小到大、行数为第二关键字从小到大、列数为第三关键字从小到大排序
  26. return cst[x.X][x.Y]!=cst[y.X][y.Y]?cst[x.X][x.Y]<cst[y.X][y.Y]:x.X!=y.X?x.X<y.X:x.Y<y.Y;
  27. }
  28. bool vis[N+1][M+1];//标记
  29. signed main(){
  30. // freopen("C:\\Users\\chenx\\OneDrive\\桌面\\data.in","r",stdin);
  31. read(n);read(m);read(n0);read(m0);
  32. for(ri i=1;i<=n;i++)for(ri j=1;j<=m;j++){
  33. read(a[i][j]);
  34. Sum[i][j]=Sum[i-1][j]+Sum[i][j-1]-Sum[i-1][j-1]+a[i][j];//预处理二维前缀和
  35. }
  36. for(ri i=1;i<=n;i++){//第一次单调队列,算mn1
  37. head=tail=0;
  38. for(ri j=1;j<m0;j++){
  39. while(head<tail&&a[i][q[tail-1]]>=a[i][j])tail--;
  40. q[tail++]=j;
  41. }
  42. for(ri j=1;j+m0-1<=m;j++){
  43. while(head<tail&&q[head]<j)head++;
  44. while(head<tail&&a[i][q[tail-1]]>=a[i][j+m0-1])tail--;
  45. q[tail++]=j+m0-1;
  46. mn1[i][j]=a[i][q[head]];
  47. }
  48. }
  49. // for(ri i=1;i<=n;i++){for(ri j=1;j+m0-1<=m;j++)cout<<mn1[i][j]<<" ";puts("");}puts("");
  50. for(ri j=1;j+m0-1<=m;j++){//第二次单调队列,算mn2
  51. head=tail=0;
  52. for(ri i=1;i<n0;i++){
  53. while(head<tail&&mn1[q[tail-1]][j]>=mn1[i][j])tail--;
  54. q[tail++]=i;
  55. }
  56. for(ri i=1;i+n0-1<=n;i++){
  57. while(head<tail&&q[head]<i)head++;
  58. while(head<tail&&mn1[q[tail-1]][j]>=mn1[i+n0-1][j])tail--;
  59. q[tail++]=i+n0-1;
  60. mn2[i][j]=mn1[q[head]][j];
  61. }
  62. }
  63. // for(ri i=1;i+n0-1<=n;i++){for(ri j=1;j+m0-1<=m;j++)cout<<mn2[i][j]<<" ";puts("");}
  64. for(ri i=1;i+n0-1<=n;i++)for(ri j=1;j+m0-1<=m;j++)cst[i][j]=calc_cst(i,j)/*存花费*/,ord.pb(mp(i,j));
  65. sort(ord.begin(),ord.end(),cmp);//排序
  66. vector<pair<int,int> > ans;//答案序列
  67. for(ri i=0;i<ord.size();i++){
  68. int x=ord[i].X,y=ord[i].Y;
  69. if(vis[x][y]||vis[x][y+m0-1]||vis[x+n0-1][y]||vis[x+n0-1][y+m0-1])continue;//判四个角
  70. ans.pb(ord[i]);//放到答案序列里
  71. for(ri j=x;j<=x+n0-1;j++)for(ri k=y;k<=y+m0-1;k++)vis[j][k]=true;//标记
  72. }
  73. cout<<ans.size()<<"\n";//输出选的小矩阵的个数
  74. for(ri i=0;i<ans.size();i++)printf("%lld %lld %lld\n",ans[i].X,ans[i].Y,cst[ans[i].X][ans[i].Y]);//输出选的小矩阵
  75. return 0;
  76. }

CodeForces 15D Map的更多相关文章

  1. codeforces 15D . Map 优先队列

    题目链接 题目意思很简单nm的矩阵里, 选若干个ab的小矩阵, 定义每个矩阵的值为这个矩阵里的所有数的和-最小值*数的个数. 选小矩阵时, 优先选值最小的,然后次小的.. 知道不能选位置. 输出所有矩 ...

  2. 通过Jedis操作Redis

    package com.yh; import org.junit.After; import org.junit.Before; import org.junit.Test; import redis ...

  3. codeforces 651C(map、去重)

    题目链接:http://codeforces.com/contest/651/problem/C 思路:结果就是计算同一横坐标.纵坐标上有多少点,再减去可能重复的数量(用map,pair存一下就OK了 ...

  4. Codeforces Round #Pi (Div. 2) C. Geometric Progression map

    C. Geometric Progression Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  5. Codeforces 600 E. Lomsat gelral (dfs启发式合并map)

    题目链接:http://codeforces.com/contest/600/problem/E 给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少. 最容 ...

  6. Codeforces Round #215 (Div. 2) B. Sereja and Suffixes map

    B. Sereja and Suffixes Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset ...

  7. Codeforces Beta Round #12 (Div 2 Only) D. Ball sort/map

    D. Ball Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/12/D D ...

  8. Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map

    E. Lomsat gelral Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/prob ...

  9. Codeforces 1136D - Nastya Is Buying Lunch - [贪心+链表+map]

    题目链接:https://codeforces.com/problemset/problem/1136/D 题意: 给出 $1 \sim n$ 的某个排列 $p$,再给出若干 $(x,y)$ 表示当序 ...

随机推荐

  1. 浅谈SpringBoot

    关于SpringBoot有哪些特性,SpringBoot官网是这么描述的: Features Create stand-alone Spring applications Embed Tomcat, ...

  2. VMware下的Centos7实践Kvm虚拟化(通俗易懂)

    虽然网上已经有很多关于kvm安装的教程了,但我还是看得头晕,有的教程里安装的包很多,有的很少,也没说明那些安装包的作用是干嘛的,用的命令也不一样,也没解释命令的意思是什么. 我重新写一个教程,尽量通俗 ...

  3. (转)代码结构中Dao,Service,Controller,Util,Model是什么意思?

    作者:技能树IT修真院链接:https://www.zhihu.com/question/58410621/answer/623496434来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  4. Perm排列计数(新博客试水,写的不好,各路大神见谅)

    B. Perm 排列计数 内存限制:512 MiB 时间限制:1000 ms 标准输入输出   题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i&l ...

  5. JavaScript知识点---->运算规则与运算(逻辑、位)

    *在js中不同类型之间的运算,所得到结果的类型也会有所变化: string + number = string string + boolean = string string + undefiend ...

  6. tomcat用做图片服务器

    最近做了个小网站,就是用tinyce富文本编辑器,https://www.511easy.com/ 保持字体排版和图片 发现博客园的图片,一天之后就无法显示 就想着自己做一个图片服务器,上传图片到指定 ...

  7. 第一篇博客 安装open live writer

    第一篇博客安装open live writer http://openlivewriter.org/ 有的人可能会打不开,所以我准备了一个百度云的链接地址 链接:https://pan.baidu.c ...

  8. STL map 详细用法

    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个称为该关键字的值)的数据 处理能力. 需要的库 #include <map> ...

  9. 原创:微信小程序如何使用自定义组件

    本博文是通过实际开发中的一个实例来讲解自定义组件的使用. 第一步:新建自定义组件目录,如图,我新建了个componts和tabList目录,然后右键tabList目录选择新建compont取名为tab ...

  10. 【iOS】App Transport Security

    iOS9中新增App Transport Security(简称ATS)特性, 主要使到原来请求的时候用到的HTTP,都转向TLS1.2协议进行传输.这也意味着所有的HTTP协议都强制使用了HTTPS ...