Solution -「CCO 2019」「洛谷 P5532」Sirtet
\(\mathcal{Description}\)
Link.
在一个 \(n\times m\) 的网格图中,每个格子上是空白 . 或沙子 #,四联通的沙子会连成一个整体。令此时所有沙子块同时开始匀速下落,下落时不同的沙子块不会再连成整体,求最终状态。
\(nm\le10^6\)。
\(\mathcal{Solution}\)
虽然切了但考点掌握得并不熟练。
考虑一列上的两堆沙子,上方一堆所在的块必然会被下方一堆所在的块托住,若从模拟入手,就是“先让后者下落,再让前者下落”。不过在下落过程中,沙块之间互相的限制关系频繁改变,很难直接维护。
定量分析“托住”的含义。设上块的最终下落高度为 \(f_u\), 下块的最终下落高度为 \(f_v\),那么同列的沙子为 \(f_u\) 和 \(f_v\) 之间加上的限制形如 \(f_u\le f_v+h\) —— 差分约束嘛。
如果像我一样对差分约束不敏感,可以尝试这种思考模式:限制复杂 —— 限制关系是一般图 —— 转化为特殊图?(生成树?缩点?圆方树?……)使用一般图上非 NPC 问题的算法?(最短路?2-SAT?差分约束?……)—— 发现限制可以表示为差分约束。
最后,这个差分约束没有负权,所以 \(\mathcal O(nm\log nm)\) 跑 Dijkstra 即可。
\(\mathcal{Code}\)
/*~Rainybunny~*/
#include <bits/stdc++.h>
#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
typedef std::pair<int, int> PII;
#define fi first
#define se second
inline void chkmin( int& u, const int v ) { v < u && ( u = v ); }
const int MAXNM = 1e6;
int n, m, cnt, **idx, lasf[MAXNM + 5], lash[MAXNM + 5];
char** grid;
int ecnt, head[MAXNM + 5], dis[MAXNM + 5];
struct Edge { int to, val, nxt; } graph[MAXNM * 2 + 5];
inline void link( const int s, const int t, const int w ) {
// printf( "%d %d %d\n", s, t, w );
graph[++ecnt] = { t, w, head[s] }, head[s] = ecnt;
}
struct DSU {
int fa[MAXNM + 5], siz[MAXNM + 5];
inline void init( const int s ) { rep ( i, 1, s ) siz[fa[i] = i] = 1; }
inline int find( const int x ) {
return x == fa[x] ? x : fa[x] = find( fa[x] );
}
inline bool unite( int x, int y ) {
if ( ( x = find( x ) ) == ( y = find( y ) ) ) return false;
if ( siz[x] < siz[y] ) x ^= y ^= x ^= y;
return siz[fa[y] = x] += siz[y], true;
}
} dsu;
inline void dijkstra() {
static std::priority_queue<PII, std::vector<PII>, std::greater<PII> > heap;
rep ( i, 0, cnt ) dis[i] = 0x3f3f3f3f;
heap.push( { dis[0] = 0, 0 } );
while ( !heap.empty() ) {
PII p( heap.top() ); heap.pop();
if ( dis[p.se] != p.fi ) continue;
for ( int i = head[p.se], v; i; i = graph[i].nxt ) {
if ( dis[v = graph[i].to] > p.fi + graph[i].val ) {
heap.push( { dis[v] = p.fi + graph[i].val, v } );
}
}
}
}
int main() {
// freopen( "tpt.in", "r", stdin );
// freopen( "tpt.out", "w", stdout );
scanf( "%d %d", &n, &m );
grid = new char*[n + 5], idx = new int*[n + 5];
rep ( i, 1, n ) {
grid[i] = new char[m + 5], idx[i] = new int[m + 5];
scanf( "%s", grid[i] + 1 );
rep ( j, 1, m ) idx[i][j] = grid[i][j] == '#' ? ++cnt : 0;
}
dsu.init( cnt );
rep ( i, 1, n ) rep ( j, 1, m ) if ( grid[i][j] == '#' ) {
if ( i > 1 && grid[i - 1][j] == '#' ) {
dsu.unite( idx[i][j], idx[i - 1][j] );
}
if ( j > 1 && grid[i][j - 1] == '#' ) {
dsu.unite( idx[i][j], idx[i][j - 1] );
}
}
rep ( i, 1, n ) rep ( j, 1, m ) if ( grid[i][j] == '#' ) {
idx[i][j] = dsu.find( idx[i][j] ), grid[i][j] = '.';
// fprintf( stderr, "(%d,%d) in %d\n", i, j, idx[i][j] );
}
rep ( i, 1, m ) lash[i] = n + 1;
per ( i, n, 1 ) rep ( j, 1, m ) if ( idx[i][j] ) {
link( lasf[j], idx[i][j], lash[j] - i - 1 );
lasf[j] = idx[i][j], lash[j] = i;
}
dijkstra();
// rep ( i, 0, cnt ) fprintf( stderr, "%d\n", dis[i] );
rep ( i, 1, n ) rep ( j, 1, m ) if ( idx[i][j] ) {
grid[i + dis[idx[i][j]]][j] = '#';
}
rep ( i, 1, n ) puts( grid[i] + 1 );
return 0;
}
Solution -「CCO 2019」「洛谷 P5532」Sirtet的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「洛谷5290」「LOJ3052」「十二省联考 2019」春节十二响【启发式合并】
题目链接 [洛谷传送门] [LOJ传送门] 题目大意 给定一棵树,每次选取树上的一个点集,要求点集中的每个点不能是另一个点的祖先,选出点集的代价为点集中权值最大点的权值,问将所有点都选一遍的最小代价为 ...
- 「洛谷5283」「LOJ3048」「十二省联考2019」异或粽子【可持久化01trie+优先队列】
题目链接 [洛谷传送门] [LOJ传送门] 题目大意 让你求区间异或和前\(k\)大的异或和的和. 正解 这道题目是Blue sky大佬教我做的(祝贺bluesky大佬进HA省A队) 我们做过某一些题 ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
- 「洛谷3338」「ZJOI2014」力【FFT】
题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...
随机推荐
- 详解nohup /dev/null 2>&1 含义的使用
https://www.jb51.net/article/169837.htm 这篇文章主要介绍了详解nohup /dev/null 2>&1 含义的使用,文中通过示例代码介绍的非常详细 ...
- PyCharm撤消/恢复
PyCharm在撤消/重做的每个步骤之前移动插入符号,然后执行撤消/重做操作. 要撤消操作,请执行以下操作之一: 在主菜单上,选择Edit | Undo. 按Ctrl+Z. 要恢复操作,请执行以下操作 ...
- Spring系列1:Spring基本概念
本文内容 什么是Spring? 为什么学Spring? 本系列包含哪些技术? 本系列适合哪些人? 什么是Spring? 基本概念 Spring 框架为现代基于 Java 的企业应用程序提供了一个全面的 ...
- java下拉框转换公共方法
1. 下拉框实例类 import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.Boolean ...
- MCU软件最佳实践——矩阵键盘驱动
1.矩阵键盘vs独立按键 在mcu应用开发过程中,独立按键比较常见,但是在需要的按键数比较多时,使用矩阵键盘则可以减少io占用,提高系统资源利用率.例如,某mcu项目要求有16个按钮,如果采用独立按键 ...
- C语言字幕从外向中间汇聚
演示数据中多个字符,从两端向中间移动,向中间汇聚 简单,粗暴,先上代码: Sleep()函数属于<windows.h>头文件中. sizeof()函数求右下标:数组内是数字时,求右下标要- ...
- 关于Jmeter线程数Ramp-Up.循环次数的理解和实验数据
1. 关于线程组参数 线程组:即一个线程组实例里面包括多个串行的请求或动作.一个线程组的从启动到结束的时间取决于你线程中的步骤数量. 线程数:即用户数,在Ramp-up时间内(包括循环),简单把线程数 ...
- rocketmq实现延迟队列精确到秒级实现方案2-时间轮和delay-file实现
上图是通过RocketMQ源码分析一个实现原理方案示意图. 分为两个部分: 消息的写入消息的Schedule 在写入CommitLog之前,如果是延迟消息,按照每10分钟写入delayfile文件,对 ...
- Solon Web 开发,十四、与Spring、Jsr330的常用注解对比
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 1011day-人口普查系统
1.Browse.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...