\(\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. CentOS6.5-Hadoop2.7.3安装hive-2.1.1

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6627723801960382979/ 系统版本,Hadoop已安装完成 Mysql安装完成 准备的解压包 安装zi ...

  2. Java 集合详解 | 一篇文章解决Java 三大集合

    更好阅读体验:Java 集合详解 | 一篇文章搞定Java 三大集合 好看的皮囊像是一个个容器,有趣的灵魂像是容器里的数据.接下来讲解Java集合数据容器. 文章篇幅有点长,还请耐心阅读.如只是为了解 ...

  3. postman设置token等关联参数

    登陆时登录成功后服务器会返回一个token,这个token作为第二步骤的入参:第二个步骤请求成功后服务器会返回一个新token,然后这个token作为第三步骤的入参!如此一来的话,要用postman做 ...

  4. winfrom 双缓冲

    在窗体load函数中 this.DoubleBuffered = true; //控件,需要反射的方式设置 Type dgvType = this.dgv.GetType(); PropertyInf ...

  5. Spark-寒假-实验3

    1.安装 Hadoop 和 Spark 进入 Linux 系统,参照本教程官网"实验指南"栏目的"Hadoop 的安装和使用",完成 Hadoop 伪分布式模式 ...

  6. 【笔记】论文阅读:《Gorilla: 一个快速, 可扩展的, 内存式时序数据库》

    英文:Gorilla: A fast, scalable, in-memory time series database 中文:Gorilla: 一个快速, 可扩展的, 内存式时序数据库

  7. 一些Markdown扩展语法

    相信很多人跟我一样,对Markdown是"一知半解",会打一点,知道一点,但是其实从没花哪怕一分钟了解过.其实除了标题粗体插入代码,Markdown还有很多有趣的基础语法和扩展语法 ...

  8. 科技爱好者周刊(第 175 期):知识广度 vs 知识深度

    这里记录每周值得分享的科技内容,周五发布. 本杂志开源(GitHub: ruanyf/weekly),欢迎提交 issue,投稿或推荐科技内容. 周刊讨论区的帖子<谁在招人?>,提供大量程 ...

  9. Simulink S-Function的使用(以串口接收MPU6050六轴陀螺仪参数为实例)

    S-Function 允许使用自定义C/C++函数作为传递函数,具有可移植性.也可以同样利用MATLAB函数进行相同的运算,看开发者熟悉程度而定. 项目流程 由系统串口接收数据包. 通过S-Funct ...

  10. web.xml最新配置

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmln ...