【vijos】1750 建房子(线段树套线段树+前缀和)
是不是我想复杂了。。。。
自己yy了个二维线段树,然后愉快的敲打。
但是wa了两法。。。。。。。sad
原因是在处理第二维的更新出现了个小问题,sad。
void pushup1(int x) { for1(i, 1, mm<<2) mn[x][i]=min(mn[lc][i], mn[rc][i]); }
这里注意是mm*4。。。我该好好想想了。。这是在dbg的时候找出来的问题。sad。
我觉得很奇怪,线段树的底层节点一共就mm个,那么整棵树不就是mm*2-1个节点吗。为嘛要开到*4。。。。求教。。
zyf神犇给的:http://scinart.github.io/acm/2014/03/19/acm-segment-tree-space-analysis/
这题很明显,我们枚举每一个点然后维护矩阵的最小值,然后前缀和剪掉就行了。
维护矩阵用线段树套线段树,log^2n,时间感人的到了5000ms。。。。sad。。也就是维护个行区间,然后维护个列区间。
我第一次写,而且是自己yy的,不知道会不会有什么常数优化?
还有听说这题是单调队列?what?(具体在我另一篇博文里,去找单调队列的分类里边应该有。。。。。很简单的。。。
套线段树自己yy一下就能出来了的,我就不说了。。不会就看代码吧。
然后计算的时候应该开longlong吧
然后在选的时候标记其实很简单,只需要考虑四个点有没有被取掉就行了,理由很简单。。。。。。。。。自己想吧。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } #define lc x<<1
#define rc x<<1|1
#define lson l, m, lc
#define rson m+1, r, rc
#define MID (l+r)>>1 typedef long long ll;
const int N=1005, oo=0x7f7f7f7f;
struct dat { int x, y; ll d; }home[N*N], ans[N*N];
bool cmp(const dat &a, const dat &b) {
if(a.d==b.d) {
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
return a.d<b.d;
}
int mn[N<<2][N<<2], a[N][N], A, B, cnt, ct, nn, mm;
bool vis[N][N];
ll sum[N][N]; void pushup1(int x) { for1(i, 1, mm<<2) mn[x][i]=min(mn[lc][i], mn[rc][i]); }
void pushup2(int *s, int x) { s[x]=min(s[lc], s[rc]); }
void build2(int l, int r, int x, int *s, int row) {
if(l==r) { s[x]=a[row][l]; return; }
int m=MID;
build2(lson, s, row); build2(rson, s, row);
pushup2(s, x);
}
void build1(int l, int r, int x) {
if(l==r) { build2(1, mm, 1, mn[x], l); return; }
int m=MID;
build1(lson); build1(rson);
pushup1(x);
}
int query2(int l, int r, int x, int *s, int L, int R) {
if(L<=l && r<=R) return s[x];
int m=MID, ret=oo;
if(L<=m) ret=min(ret, query2(lson, s, L, R));
if(m<R) ret=min(ret, query2(rson, s, L, R));
return ret;
}
int query1(int l, int r, int x, int L, int R, int LL, int RR) {
if(L<=l && r<=R) return query2(1, mm, 1, mn[x], LL, RR);
int m=MID, ret=oo;
if(L<=m) ret=min(ret, query1(lson, L, R, LL ,RR));
if(m<R) ret=min(ret, query1(rson, L, R, LL, RR));
return ret;
}
ll ask(int x, int y) {
int ret=query1(1, nn, 1, x, x+A-1, y, y+B-1); //printf("%d %d %d\n", x, y, ret);
ll s=sum[x][y]-sum[x+A][y]-sum[x][y+B]+sum[x+A][y+B];
return s-(ll)ret*(ll)A*(ll)B;
}
void dfs(int x, int y, int a, int b) {
if(vis[x][y]) return;
vis[x][y]=1;
if(a<A) dfs(x+1, y, a+1, b);
if(b<B) dfs(x, y+1, a, b+1);
}
void init() {
CC(mn, 0x7f);
read(nn); read(mm); read(A); read(B);
for1(i, 1, nn) for1(j, 1, mm) read(a[i][j]);
//for1(i, 1, nn) { for1(j, 1, mm) printf("%d\t", a[i][j]); puts(""); }
for3(i, nn, 1) for3(j, mm, 1) sum[i][j]=sum[i+1][j]+sum[i][j+1]-sum[i+1][j+1]+a[i][j];
build1(1, nn, 1);
for1(i, 1, nn-A+1) for1(j, 1, mm-B+1) {
home[++cnt].x=i;
home[cnt].y=j;
home[cnt].d=ask(i, j);
}
}
int main() {
init();
sort(home+1, home+1+cnt, cmp);
for1(i, 1, cnt) {
int x=home[i].x, y=home[i].y;
if(!vis[x][y] && !vis[x+A-1][y] && !vis[x][y+B-1] && !vis[x+A-1][y+B-1]) {
ans[++ct]=home[i];
dfs(x, y, 1, 1);
}
}
printf("%d\n", ct);
for1(i, 1, ct) printf("%d %d %lld\n", ans[i].x, ans[i].y, ans[i].d);
return 0;
}
背景
安得广厦千万间,天下寒士俱欢颜。
描述
小D终于成为了一位建筑师。他的第一个任务是在一块n行m列的矩形土地上砌房子,每个房子的大小是a行b列(不能旋转)。
矩形土地的每个单元格都有一个高度。如果选定某个区域上为建房子的地方,那么需要将这个区域的每个单元格的高度变成这个区域的最小的单元格的高度,因为这样能使土地更平整。将一个单元格的高度从h2变为h1所花费的代价是h2-h1,一个区域所花费的代价为其每个单元格所花费的代价之和。
现在小D按下面所述的方式建房子:
1、首先找到矩形土地中花费最少代价就能建房子的区域(这个区域中不能有某个单元格已经砌了房子),如果有多个这样的区域,选择左上角所在行尽可能小的,如果行相同,选择列尽可能小的。
2、接下来在这块区域砌一栋房子。
3、重复上述操作,直到找不到一个可以砌房子的区域。
现在需要你告诉小D,他一共将砌多少栋房子,每栋房子的左上角的坐标,以及每栋房子所花费的代价。
格式
输入格式
输入的第一行包括四个正整数
n,m,a,b(含义如上所述)
接下来n行,每行m个非负整数
其中第i行,第j列表示第i行,第j列的单元格的高度。
输出格式
输出第一行为一个非负整数S:表示一共砌了多少栋房子
接下来S行
每行三个整数i,j,v:表示第S个房子的左上角的所在行,所在列,以及所花费的代价。
样例2
限制
每个测试点2s
提示
30%保证:n <= 10, m <= 10
70%保证:n <= 300, m <= 300
100%保证:n <= 1000, m <= 1000
1<= a <= n, 1 <= b <= m, 每个单元格的高度 <= 10^9
来源
codeforces
【vijos】1750 建房子(线段树套线段树+前缀和)的更多相关文章
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- ZJOI 2017 树状数组(线段树套线段树)
题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...
- BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)
题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...
- hdu-4819-线段树套线段树
http://acm.hdu.edu.cn/showproblem.php?pid=4819 给出一个N*N的矩阵,每次询问一个m*m的子矩阵里的floor((maxv+minv)/2)并把中间的元素 ...
- dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448
4448: [Scoi2015]情报传递 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 588 Solved: 308[Submit][Status ...
- [TJOI2017][bzoj4889] 不勤劳的图书管理员 [线段树套线段树]
题面 传送门 思路 考虑两本书的位置交换对答案的贡献: (为了方便描述,用"左边那本"和"右边那本"称呼两本我们要交换的书,"中间那本"是我 ...
- 【bzoj4785】[Zjoi2017]树状数组 线段树套线段树
题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作 ...
- BZOJ1901 ZOJ2112 线段树+treap (线段树套线段树)
BZOJ1901: 线段树套线段树做法: (外层线段树 里层动态开节点的权值线段树) 有一个小小的trick 可以省掉二分变成nlog^2n的 就是把查询的区间都取出来- logn个一起走- 2016 ...
随机推荐
- 无埋点数据收集和adb monkey测试屏蔽通知栏
简单记录百度移动统计android无埋点sdk使用和monkey测试屏蔽通知栏的问题 1.无埋点sdk使用 很简单,下载完sdk后导入到项目中 , 参考sdk文档进行就可以了,个人觉得比友盟还简单,几 ...
- 细数Python的特殊方法一:集合类
1. 特殊方法汇总列表 2. 仿集合类 __len__:返回对象的长度 __getitem__:获得某一项的值 __setitem__:设置莫一项的值 __delitem__删除某一项 __c ...
- [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新全然解读
---------------------------------------------------------------------------------------------------- ...
- 1000个经常使用的Python库和演示样例代码
以下是programcreek.com通过分析大量开源码,提取出的最经常使用的python库. 1. sys (4627) 2. os (4088) 3. re (3563) 4 ...
- 阻塞与非阻塞、同步与异步、I/O模型
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就是在c端 ...
- 关于Eric 6的后端调试器无法启动错误 [The Debugger backend could not be started]
声明: 1)本文由我bitpeach原创撰写.本篇如有转载,请注明来源. 2)本篇主要谈Eric6的一个怪异错误.因为篇幅不长,只是一个短记,以备档查阅. 1.1 软件环境 (1)Eirc6 ,版本号 ...
- Java之基础(1) - 编程中“为了性能”尽量要做到的一些地方
最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源总结的一些在Ja ...
- java new map
import com.google.common.collect.Maps; public static Map<String, Object> configMap2 = new Conc ...
- 反射与annotation
1,可以通过反射取得使用的全部annotation 2,可以通过反射取得指定的annotation. 一个annotation要想变得有意义, 必须结合反射机制取得annotation中设置的全部内容 ...
- MongoDB - 内嵌角色
数据库用户角色(每个数据库都有的角色) 角色名 说明 read 对non-system集合的读取权限,以及以下system集合的读取权限:system.indexes,system.js,syst ...