题解 [AGC026D] Histogram Coloring

传送门

一开始想按行处理
等 DP 式子都写出来了发现限制可以跨多行
然后人麻了

考虑从上到下按列处理
发现若某一行存在两个相邻同色元素,则下一行必须反色
否则若这一行是红蓝交错排布,则下一行可以同色也可以反色
又发现按列处理的话可以用最小值划分子问题
所以考虑从上到下处理 solve(l, r, base)\([l, r]\) 内高于 base 的行的方案数
发现这部分元素的最下面一行是不是红蓝交错会影响转移,所以放到 DP 状态里
\(f_{i, 0/1}\) 表示划分出的第 \(i\) 个部分最下面一行任意/红蓝相间的方案数
若当前行红蓝相间,则只要求上面的子区间最下面的行都是红蓝相间
当前部分 \(\leqslant minh\) 的部分形成一个矩形,其中每一行都可以与上一行相同或相反
所以

\[f_{i, 1}=2^{minh-base}\prod f_{j, 1} \]

考虑当前矩形最上面一行不是红蓝相间,则需要被子区间覆盖的部分反色,其余任意,再减去红蓝相间的方案数即可
此时矩形中每一行都必须与上一行相反
所以

\[f_{i, 0}=f_{i, 1}+2^{cnt}\prod(f_{j, 0}+f_{j, 1})-2\prod f_{j, 1} \]

复杂度 \(O(n^2)\),可以再优化但 \(n\leqslant 100\) 所以没有意义

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 110
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
ll f[N*N][2];
int h[N], tot;
const ll mod=1e9+7;
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}

int solve(int l, int r, int base) {
	// cout<<"solve: "<<l<<' '<<r<<endl;
	int minh=INF, cnt=0, u=++tot;
	vector<int> to;
	for (int i=l; i<=r; ++i) minh=min(minh, h[i]);
	for (int i=l; i<=r; ++i) if (h[i]==minh) ++cnt;
	for (int p1=l,p2; p1<=r; p1=p2+1) {
		while (p1<=r&&h[p1]==minh) ++p1;
		for (p2=p1; p2<r&&h[p2+1]!=minh; ++p2);
		if (p1<=r) to.pb(solve(p1, p2, minh));
	}
	ll prod=1;
	for (auto v:to) prod=prod*f[v][1]%mod;
	f[u][1]=qpow(2, minh-base)*prod%mod;
	f[u][0]=qpow(2, cnt);
	for (auto v:to) f[u][0]=f[u][0]*(f[v][0]+f[v][1])%mod;
	f[u][0]=(f[u][1]+f[u][0]-2*prod)%mod;
	return u;
}

signed main()
{
	n=read();
	for (int i=1; i<=n; ++i) h[i]=read();
	printf("%lld\n", (f[solve(1, n, 0)][0]%mod+mod)%mod);

	return 0;
}
posted @ 2022-06-01 10:09  Administrator-09  阅读(1)  评论(0编辑  收藏  举报