\(\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的更多相关文章

  1. Solution -「AGC 036D」「AT 5147」Negative Cycle

    \(\mathcal{Descriprtion}\)   Link.   在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...

  2. Solution -「AGC 016F」Games on DAG

    \(\mathcal{Description}\)   Link.   给定一个含 \(n\) 个点 \(m\) 条边的 DAG,有两枚初始在 1 号点和 2 号点的棋子.两人博弈,轮流移动其中一枚棋 ...

  3. Solution -「AGC 004E」「AT 2045」Salvage Robots

    \(\mathcal{Description}\)   Link.   有一个 \(n\times m\) 的网格.每个格子要么是空的,要么有一个机器人,要么是一个出口(仅有一个).每次可以命令所有机 ...

  4. Solution -「AGC 012F」「AT 2366」Prefix Median

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_{2n-1}\}\),将 \(\{a_{2n-1}\}\) 按任意顺序排列后,令序列 \(b_i\) 为前 ...

  5. Solution -「AGC 010C」「AT 2304」Cleaning

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的无根树,点有点权,每次选择两个不同的叶子,使它们间的简单路径的所有点权 \(-1\),问能否将所有点 ...

  6. Solution -「AGC 019E」「AT 2704」Shuffle and Swap

    \(\mathcal{Description}\)   Link.   给定 \(01\) 序列 \(\{A_n\}\) 和 \(\{B_n\}\),其中 \(1\) 的个数均为 \(k\).记 \( ...

  7. Solution -「AGC 019F」「AT 2705」Yes or No

    \(\mathcal{Description}\)   Link.   有 \(n+m\) 个问题,其中 \(n\) 个答案为 yes,\(m\) 个答案为 no.每次你需要回答一个问题,然后得知这个 ...

  8. Solution -「AGC 013E」「AT 2371」Placing Squares

    \(\mathcal{Description}\)   Link.   给定一个长度为 \(n\) 的木板,木板上有 \(m\) 个标记点,第 \(i\) 个标记点距离木板左端点的距离为 \(x_i\ ...

  9. Solution -「AGC 003D」「AT 2004」Anticube

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个数 \(a_i\),要求从中选出最多的数,满足任意两个数之积都不是完全立方数.   \(n\le10^5\) ...

随机推荐

  1. Tomcat8/9的catalina.out中文乱码问题解决

    OS: Red Hat Enterprise Linux Server release 7.8 (Maipo) Tomcat: 9 中文显示为???问号 在$CATALINA_HOME/conf下的l ...

  2. 总结关于spring security 使用 JWT 和 账户密码登录 整合在一起的新感悟

    (1)jwt登录拦截,需要在账户密码认证之前进行jwt认证,因此jwt拦截需要在 UsernamePasswordAuthenticationFilter 之前: (2)jwt验证通过则不需要执行账户 ...

  3. 安装与配置文本编辑器vim

    1.安装 查看是否已经安装vim,在命令行敲入"vi"后按"tab"键,如果只看到有默认的vi和vim.tiny,则为未安装,vim.tiny是vim的精简版 ...

  4. 实验 4 :Open vSwitch 实验 —— Mininet 中使用 OVS 命令

    实验 4 :Open vSwitch 实验 -- Mininet 中使用 OVS 命令 一.实验目的 Mininet 安装之后,会连带安装 Open vSwitch,可以直接通过 Python 脚本调 ...

  5. springBoot--原理分析

    起步依赖分析 分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-star ...

  6. GNU C字节对齐__attribute__((aligned(n))) #pragma pack(n)

    在阅读gnu软件c源代码时,经常会遇到字节对齐相关操作,比如uboot命令相关的代码中,会遇到__attribute__((aligned(n)))扩展关键字,#pragma pack(n)预处理指令 ...

  7. Python函数与lambda 表达式(匿名函数)

    Python函数 一.函数的作用 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段 函数能提高应用的模块性和代码的重复利用率 python 内置函数:https://docs.pytho ...

  8. Vulnhub - THE PLANETS: EARTH

    环境配置 从www.vulnhub.com下载靶机,在VMware中导入,自动分配IP 主机发现 通过对内网主机的扫描,VMware为目标主机 端口扫描 使用nmap对主机进行扫描 发现443端口信息 ...

  9. Android学习笔记4

    activity配置文件 //AndroidMainifest.xml <?xml version="1.0" encoding="utf-8"?> ...

  10. 【程序5】输入三个整数x,y,z,请把这三个数由小到大输出

    我自己写的: x = int(input('x:')) y = int(input('y:')) z = int(input('z:')) L = [x,y,z] print(sorted(L)) 官 ...