Codeforces 15D Map 单调队列+构造
来源:互联网 发布:挺进大别山 知乎 编辑:程序博客网 时间:2024/06/13 10:53
题目链接:http://codeforces.com/problemset/problem/15/D
题意:给定n*m的矩阵,每个点都是一个地基,上面的数字表示该地基的高度。
再给定a*b的小房子,要把a*b放在这个矩阵上,显然建房子要保证选取的地基高度一致。
若不一致,则要把选取的a*b大的矩阵中所有地基都挖低使得和其中一块最矮的地基高度一样,花费是挖的高度和
操作:
选取当前花费最小的一块矩阵,在上面建房子,若有多个方案花费一样,则优先选左上角的。
问:
建的房子的左上角坐标和建该房子的花费
思路:
显然我们要先求出选取每个点时,这个点的地基。用单调队列求一次行的,再在这基础上求一次列的就能得到这个点的地基。
然后把所有点都扔到堆里,跑出解即可。
双端队列的简单用法:
deque<int>q;
q.empty();
q.pop_front(); q.pop_back();
q.push_back(i); q.push_front(i);
单调队列:队尾->队首,队列中存的不是数组的元素,而是数组的下标
单调队列求最小就用递增,对于某一个数要求出这个数u到u+len-1的长度内的最小值:
对于i点,则要求出i点的最小值,我们不能直接求[ i, i+len-1]的值,而是求出[i-len+1, i]的最小值,然后转移到上述的 [u,u+len-1] 上
继续讨论对于i点在单调队列中的求解
1、则队尾元素必须是 [i-len+1,i]区间上的,所以 q.back()>=i-len+1,即->当{ q.back()+len-1<i } 时要把q.back()弹掉
2、要保持单调递增,所以当把这个元素x[i]加入队列时, q.front()必须<=x[i], 所以当 { q.front()>x[i] } 时要把q.front()弹掉
3、此时加入x[i],则此队列的数都在 [i-len+1,i]区间上且元素都是单调递增的,最小的元素是 x[q.back()]
4、显然x[i]的最小值就是 x[q.back()] ,到此计算出x[i]的最小值了
#include<stdio.h>#include<iostream>#include<string.h>#include<set>#include<vector>#include<map>#include<math.h>#include<queue>#include<string>#include<stdlib.h>#include<algorithm>using namespace std;#define N 1015#define LL __int64#define ll intll x[N], dou[N];void work(ll len, ll top){ deque<ll>q;// q.front() -> q.back()for(ll i = 1; i <= top; i++) {while(!q.empty() && q.front() + len <= i)q.pop_front();while(!q.empty() && x[i] <= x[q.back()]) q.pop_back();q.push_back(i);dou[i] = x[q.front()];}}ll n, m, a, b;struct node{ll x,y;LL val;node(ll a1=0,ll a2=0,LL a3=0):x(a1),y(a2),val(a3){}bool operator<(const node& Node) const{if(Node.val==val){if(Node.x==x) return Node.y<y;else return Node.x<x;}else return Node.val<val;}};priority_queue<node>q;vector<node>ans;bool use[N][N];void go(){ans.clear();while(!q.empty()){node u =q.top(); q.pop();if(use[u.x][u.y] || use[u.x+a-1][u.y+b-1] || use[u.x][u.y+b-1] || use[u.x+a-1][u.y])continue;ans.push_back(u);for(ll i = u.x; i < u.x+a; i++)for(ll j = u.y; j < u.y+b; j++)use[i][j] = 1;}ll siz = ans.size();printf("%d\n",siz);for(ll i = 0; i < siz; i++) printf("%d %d %I64d\n",ans[i].x,ans[i].y,ans[i].val);}ll val[N][N], mp[N][N];LL sum[N][N];int main(){ll i,j;while(~scanf("%d %d %d %d",&n,&m,&a,&b)) {for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&mp[i][j]);sum[i][j] = (LL)mp[i][j] + sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];}for(i=1;i<=n;i++) {memcpy(x, mp[i], sizeof x);work(b, m);for(j=1;j<=m;j++) val[i][j] = dou[j];}for(i=b;i<=m;i++) {for(j=1;j<=n;j++) x[j] = val[j][i];work(a, n);for(j=1;j<=n;j++) val[j][i] = dou[j];}for(i=a; i<=n; i++)for(j=b;j<=m;j++)q.push(node(i-a+1,j-b+1,sum[i][j]-sum[i-a][j]-sum[i][j-b]+sum[i-a][j-b]-(LL)a*(LL)b*(LL)val[i][j]));go();}return 0;}
- Codeforces 15D Map 单调队列+构造
- CodeForces 15D Map 单调队列优化
- codeforces 253D 单调队列 好题
- CodeForces 15D Map
- CodeForces Exposition && 单调队列
- CodeForces 15D Map (RMQ)
- Codeforces Round #291 (Div. 2) D. R2D2 and Droid Army RMQ/单调队列/尺取法
- 单调队列1004 Codeforces Round #154 (Div. 2) 253D. Table with Letters - 2
- 【构造】CodeForces 389D
- codeforces 655D (构造)
- Codeforces 550D 构造
- Codeforces 798D 构造
- map--codeforces,519D.
- CF 172(div2) D(单调队列)
- 单调队列 CodeForces 91B Queue
- codeforces 602 D. Lipshitz Sequence (单调栈)
- Codeforces gym 101102 D 单调栈
- codeforces #306D Polygon 构造
- Java处理特殊字符替换(正则表达式)
- Linux目录结构(二)
- 无法连接到逻辑磁盘管理器服务
- Provisioning a SQL Server Virtual Machine on Azure
- Leetcode【8】:String to Integer(atoi)
- Codeforces 15D Map 单调队列+构造
- 第10条:始终要覆盖toString
- android 网络编程之http 通信
- 浏览器 缓存与刷新 机制
- public、private、protected的作用域,以及不写时的区别
- 1021. Deepest Root
- Linux netfilter 学习笔记 之七 ip层netfilter的连接跟踪模块的概念及相关的数据结构分析
- XHTML和HTML的区别
- Spring ICO使用