Solution -「AGC 026D」Histogram Coloring
\(\mathcal{Description}\)
Link.
有 \(n\) 列下底对齐的方格纸排成一行,第 \(i\) 列有 \(h_i\) 个方格。将每个方格染成黑色或白色,求使得任意完整 \(2\times2\) 矩形内恰有两个白色(和两个黑色)的方案数。答案模 \(10^9+7\)。
\(n\le100\),\(h_i\le10^9\)
\(\mathcal{Solution}\)
小清新 DP 题叭。
首先考虑在完整的网格图里染色,若某一行完成染色,那么下一行的方案并不多:
- 若当前行存在相邻同色格,则下一行必须为当前行颜色取反;
- 否则即当前行为黑白或白黑交替,则下一行可以与当前行全部相同或全部相反。
把这一结论放在本题,建出小根笛卡尔树(根据题意,当前区间最小值应缩为一点,严格意义上不是笛卡尔树,不难意会 qwq),DP。转移问题形如将若干小块网格下面垫一大块完整网格图,求方案数。所以,令 \(f(u,0/1)\) 表示完成 \(u\) 所代表区间的染色,且最下一层是否是黑白交替状的方案数。转移平凡,可参考易读的代码。
转移里有个快速幂,最终复杂度为 \(\mathcal O(n\log h)\)。
\(\mathcal{Code}\)
/* Clearink */
#include <cstdio>
#define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
const int MAXN = 100, MOD = 1e9 + 7;
int n, h[MAXN + 5];
int node, ecnt, lef[MAXN + 5], rig[MAXN + 5],
hgt[MAXN + 5], tot[MAXN + 5], head[MAXN + 5];
struct Edge { int to, nxt; } graph[MAXN + 5];
inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
inline int mpow( int a, int b ) {
int ret = 1;
for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
return ret;
}
inline void link( const int s, const int t ) {
graph[++ecnt] = { t, head[s] }, head[s] = ecnt;
}
inline int build( const int l, const int r ) {
if ( l > r ) return 0;
int u = ++node;
hgt[u] = 0x3f3f3f3f, tot[u] = 0;
lef[u] = l, rig[u] = r;
rep ( i, l, r ) {
if ( h[i] < hgt[u] ) hgt[u] = h[i], tot[u] = 0;
tot[u] += h[i] == hgt[u];
}
for ( int i = l, j; i <= r; i = j + 1 ) {
if ( h[j = i] == hgt[u] ) continue;
while ( j + 1 <= r && h[j + 1] != hgt[u] ) ++j;
int v = build( i, j );
link( u, v ), hgt[v] -= hgt[u];
}
return u;
}
int f[MAXN + 5][2];
inline void solve( const int u ) {
int &f0 = f[u][0] = 1, &f1 = f[u][1] = 2, len = rig[u] - lef[u] + 1;
for ( int i = head[u], v; i; i = graph[i].nxt ) {
solve( v = graph[i].to ), len -= rig[v] - lef[v] + 1;
f0 = mul( f0, add( f[v][0], add( f[v][1], f[v][1] ) ) ),
f1 = mul( f1, f[v][1] );
}
f0 = mul( f0, mpow( 2, len ) ),
subeq( f0, f1 ),
f1 = mul( f1, mpow( 2, hgt[u] - 1 ) );
}
int main() {
scanf( "%d", &n );
rep ( i, 1, n ) scanf( "%d", &h[i] );
solve( build( 1, n ) );
printf( "%d\n", add( f[1][0], f[1][1] ) );
return 0;
}
Solution -「AGC 026D」Histogram Coloring的更多相关文章
- Solution -「AGC 036D」「AT 5147」Negative Cycle
\(\mathcal{Descriprtion}\) Link. 在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...
- Solution -「AGC 016F」Games on DAG
\(\mathcal{Description}\) Link. 给定一个含 \(n\) 个点 \(m\) 条边的 DAG,有两枚初始在 1 号点和 2 号点的棋子.两人博弈,轮流移动其中一枚棋 ...
- Solution -「AGC 004E」「AT 2045」Salvage Robots
\(\mathcal{Description}\) Link. 有一个 \(n\times m\) 的网格.每个格子要么是空的,要么有一个机器人,要么是一个出口(仅有一个).每次可以命令所有机 ...
- Solution -「AGC 012F」「AT 2366」Prefix Median
\(\mathcal{Description}\) Link. 给定序列 \(\{a_{2n-1}\}\),将 \(\{a_{2n-1}\}\) 按任意顺序排列后,令序列 \(b_i\) 为前 ...
- Solution -「AGC 010C」「AT 2304」Cleaning
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个点的无根树,点有点权,每次选择两个不同的叶子,使它们间的简单路径的所有点权 \(-1\),问能否将所有点 ...
- Solution -「AGC 019E」「AT 2704」Shuffle and Swap
\(\mathcal{Description}\) Link. 给定 \(01\) 序列 \(\{A_n\}\) 和 \(\{B_n\}\),其中 \(1\) 的个数均为 \(k\).记 \( ...
- Solution -「AGC 019F」「AT 2705」Yes or No
\(\mathcal{Description}\) Link. 有 \(n+m\) 个问题,其中 \(n\) 个答案为 yes,\(m\) 个答案为 no.每次你需要回答一个问题,然后得知这个 ...
- Solution -「AGC 013E」「AT 2371」Placing Squares
\(\mathcal{Description}\) Link. 给定一个长度为 \(n\) 的木板,木板上有 \(m\) 个标记点,第 \(i\) 个标记点距离木板左端点的距离为 \(x_i\ ...
- Solution -「AGC 003D」「AT 2004」Anticube
\(\mathcal{Description}\) Link. 给定 \(n\) 个数 \(a_i\),要求从中选出最多的数,满足任意两个数之积都不是完全立方数. \(n\le10^5\) ...
随机推荐
- Tomcat8/9的catalina.out中文乱码问题解决
OS: Red Hat Enterprise Linux Server release 7.8 (Maipo) Tomcat: 9 中文显示为???问号 在$CATALINA_HOME/conf下的l ...
- 总结关于spring security 使用 JWT 和 账户密码登录 整合在一起的新感悟
(1)jwt登录拦截,需要在账户密码认证之前进行jwt认证,因此jwt拦截需要在 UsernamePasswordAuthenticationFilter 之前: (2)jwt验证通过则不需要执行账户 ...
- 安装与配置文本编辑器vim
1.安装 查看是否已经安装vim,在命令行敲入"vi"后按"tab"键,如果只看到有默认的vi和vim.tiny,则为未安装,vim.tiny是vim的精简版 ...
- 实验 4 :Open vSwitch 实验 —— Mininet 中使用 OVS 命令
实验 4 :Open vSwitch 实验 -- Mininet 中使用 OVS 命令 一.实验目的 Mininet 安装之后,会连带安装 Open vSwitch,可以直接通过 Python 脚本调 ...
- springBoot--原理分析
起步依赖分析 分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-star ...
- GNU C字节对齐__attribute__((aligned(n))) #pragma pack(n)
在阅读gnu软件c源代码时,经常会遇到字节对齐相关操作,比如uboot命令相关的代码中,会遇到__attribute__((aligned(n)))扩展关键字,#pragma pack(n)预处理指令 ...
- Python函数与lambda 表达式(匿名函数)
Python函数 一.函数的作用 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段 函数能提高应用的模块性和代码的重复利用率 python 内置函数:https://docs.pytho ...
- Vulnhub - THE PLANETS: EARTH
环境配置 从www.vulnhub.com下载靶机,在VMware中导入,自动分配IP 主机发现 通过对内网主机的扫描,VMware为目标主机 端口扫描 使用nmap对主机进行扫描 发现443端口信息 ...
- Android学习笔记4
activity配置文件 //AndroidMainifest.xml <?xml version="1.0" encoding="utf-8"?> ...
- 【程序5】输入三个整数x,y,z,请把这三个数由小到大输出
我自己写的: x = int(input('x:')) y = int(input('y:')) z = int(input('z:')) L = [x,y,z] print(sorted(L)) 官 ...