link

题意:

给定n列的方块,第i列高度$h_i$。现在要把它染成红蓝两色,要求满足:对于任意一个$2\times 2$的区域,恰有2个蓝色,2个红色。问方案数。

$n\leq 100,h_i\leq10^9.$

题解:

观察到一个性质:对于同行相邻两个格子,如果颜色相同,那么下一行的颜色必定取反;否则下一行可以取反也可以不取。那么,对于任一行,如果存在相邻两个格子颜色相同,下一行的染色方法唯一;否则存在两种染色方案。(以下所述的“存在/不存在”都是指“存在/不存在相邻两个格子颜色相同”)

考虑保存两个量:first:存在相邻格子颜色相同情况的方案数;second:不存在的方案数(固定第一个格子的颜色,也就是最终答案需要乘2)。

如果是一个矩形很容易计算答案。否则定义solve(l,r,lim)表示区间[l,r]比lim高的部分染色方案数,每次对于这段区间把下面整块矩形的部分砍掉,上面部分递归处理。用s0,s1维护上方有方格的列,当前行存在/不存在的方案数,那么可以方便地和上方没有方格的部分合并答案。注意计数过程中一些细节问题。

时间复杂度$\mathcal{O}(n^2)$。

code:

 #include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
#define inf 1000000001
#define y1 y1___
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
char gc(){
static char buf[],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
ll read(){
char ch=gc();ll x=;int op=;
for (;!isdigit(ch);ch=gc()) if (ch=='-') op=-;
for (;isdigit(ch);ch=gc()) x=(x<<)+(x<<)+ch-'';
return x*op;
}
#define N 105
#define mod 1000000007
int ksm(int x,int p){
int ret=;
for (;p;p>>=,x=(ll)x*x%mod) if (p&) ret=(ll)ret*x%mod;
return ret;
}
int n,h[N];
pii solve(int l,int r,int lim){//区间[l,r]比lim高的部分的方案数
int mi=inf,cnt=;pii ret;//first:存在相邻格子颜色相同情况的方案数;second:不存在的方案数(固定第一个格子的颜色)
rep (i,l,r) if (h[i]<mi) mi=h[i],cnt=;else if (h[i]==mi) cnt++;
if (cnt==r-l+){//矩形
ret.fi=(ksm(,r-l+)+mod-)%mod;
ret.se=ksm(,mi-lim-);
return ret;
}
int rest=r-l+,s0=,s1=,last=;//rest:上方没有方格的列数;s0,s1:维护上方有方格的列,当前行存在/不存在的方案数
rep (i,l,r+)
if (!last&&h[i]>mi) last=i;
else if (last&&(h[i]<=mi||i>r)){
rest-=i-last;
pii tmp=solve(last,i-,mi);//子问题,递归求解
s0=(ll)s0*(tmp.fi+4ll*tmp.se%mod)%mod;//*4是因为上一行可以取反,当前行亦然,2*2
s1=(ll)s1*(2ll*tmp.se%mod)%mod;
last=;
}
s0=(s0+mod-s1)%mod;
ret.fi=(ll)s0*ksm(,rest)%mod;//如果上方方格已经存在,剩下的列随意
ret.fi=(ret.fi+(ll)s1*(ksm(,rest)+mod-)%mod)%mod;//否则需要去掉两种不合法的情况
ret.se=(ll)s1*ksm(,mi-lim-)%mod;//固定第一个格子(第一行)颜色
return ret;
}
int main(){
n=read();rep (i,,n) h[i]=read();
if (n==){//注意特判
printf("%d\n",ksm(,h[]));
exit();
}
int ex=;
rep (i,,n) if (h[i]>h[i-]&&h[i]>h[i+]){
ex=(ll)ex*ksm(,h[i]-max(h[i-],h[i+]))%mod;
h[i]=max(h[i-],h[i+]);
}
pii ans=solve(,n,);
printf("%d",(ll)ex*(ans.fi+2ll*ans.se%mod)%mod);
return ;
}

易错:

n=1的时候需要特判,因为否则的话调用ksm的时候p会变负,导致TLE。

AGC026D Histogram Coloring的更多相关文章

  1. AtCoder Grand Contest 026 D - Histogram Coloring

    一列中有两个连续的元素,那么下一列只能选择选择正好相反的填色方案(因为连续的地方填色方案已经确定,其他地方也就确定了) 我们现将高度进行离散化到Has数组中,然后定义dp数组 dp[i][j] 表示前 ...

  2. AGC 26 D Histogram Coloring

    题目 将柱子的高度离散化$\DeclareMathOperator{\dp}{dp}$ 设第 $i$ 根柱子实际高度是 $h_i$,离散化之后的高度是 $g_i$:第 $i$ 高的高度是 $H_i$, ...

  3. Solution -「AGC 026D」Histogram Coloring

    \(\mathcal{Description}\)   Link.   有 \(n\) 列下底对齐的方格纸排成一行,第 \(i\) 列有 \(h_i\) 个方格.将每个方格染成黑色或白色,求使得任意完 ...

  4. 【AtCoder】AGC026 题解

    A - Colorful Slimes 2 找相同颜色的一段,然后答案加上段长除2下取整 代码 #include <iostream> #include <cstdio> us ...

  5. DP 题集 2

    关于 DP 的一些题目 String painter 先区间 DP,\(dp[l][r]\) 表示把一个空串涂成 \(t[l,r]\) 这个子串的最小花费.再考虑 \(s\) 字符串,\(f[i]\) ...

  6. [LeetCode] Largest Rectangle in Histogram 直方图中最大的矩形

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  7. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

  8. LeetCode 笔记系列 17 Largest Rectangle in Histogram

    题目: Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar he ...

  9. LeetCode: Largest Rectangle in Histogram(直方图最大面积)

    http://blog.csdn.net/abcbc/article/details/8943485 具体的题目描述为: Given n non-negative integers represent ...

随机推荐

  1. 【洛谷 P3965】 [TJOI2013]循环格(费用流)

    题目链接 回路限制经典题. 每个点拆成入点和出点,源点连每个点的出点,流量1,费用0,每个点出点连汇点,流量1,费用0,入点和出点之间没有边. 也就是说每个点必须靠其他点流来的流量来流入汇点,同时自己 ...

  2. eclipse加速/Nginx配置跨域代理

    下班时间到啦! --下班都是他们的,而我,还是什么都没有. eclipse加速 去掉包含js文件的包的js验证,否则每次启动都需要进行校验(右击项目->properties) Nginx配置跨域 ...

  3. VC调用易语言DLL

    易语言方面: .版本 .子程序 show, , 公开 ' 本名称子程序用作测试程序用,仅在开发及调试环境中有效,编译发布程序前将被系统自动清空,请将所有用作测试的临时代码放在本子程序中. ***注意不 ...

  4. idea 控制台乱码

    第一步:修改intellij idea配置文件: 找到intellij idea安装目录,bin文件夹下面idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,分别 ...

  5. 【转载】C#异常Retry通用类

    //Retry机制 public static class Retry { /// <summary> /// 重试零个参数无返回值的方法 /// </summary> /// ...

  6. UOJ#58/BZOJ 3052【WC2013】糖果公园

    好写好调的莫队算法,就算上树了仍然好写好调. 传送门 http://uoj.ac/problem/58 简要做法 将树按照dfs序分块,然后将询问按照(u所在块,v所在块,时间)作为关键字进行排序,依 ...

  7. centos 6.5配置ftp服务器,亲测可用

    设置开机启动 1 chkconfig vsftpd on 启动服务 1 /sbin/service vsftpd start 配置FTP用户组/用户以及相应权限 添加用户组 1 groupadd ft ...

  8. linux和windows下TIME_WAIT过多的解决办法

    http://www.51testing.com/html/48/202848-249774.html linux和windows下TIME_WAIT过多的解决办法 http://m.sohu.com ...

  9. HDU 1686 Oulipo(KMP变形求子串出现数目(可重))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目大意:给两个字符串A,B求出A中出现了几次B(计算重复部分). 解题思路:稍微对kmp()函 ...

  10. js学习笔记1:语法、数据类型与转换、运算符与运算

    注意: 上部代码错误,将停止运行,下部的代码无法显示            typeof 用来定义内容类型,不会输出内容只会输出类型 一.js输出语法         1. 弹窗输出('')内的内容: ...