AGC026D Histogram Coloring

Histogram Coloring

给定一个(10^9)(n)列的表格,从左往右、从上往下标号,并去掉一些格子,使得第(i)列只剩下下面的(h_i)行格子。

要求对剩下的格子染成红蓝两种颜色,使得每个(2 × 2)的格子里面有恰好(2)个红色格子、 (2)个蓝色格子。

求方案数,对大质数取模。

(n ≤ 100, ∀1 ≤ i ≤ n, h_i ≤ 10^9)

题解

仓鼠《动态规划选讲》。

首先考虑一个完整的矩形如何计数答案

假如已经决定了前面的行,要新增一行。首先可以把上面一行全部翻转当成新增一行;特殊地,当上面一行是黑白相间的,可以直接把上面一行复制下来。

对于原问题考虑笛卡尔树DP,实际上就是每次把最低的一层给消掉。这样也构成了一个树的结构,然后从下往上DP,每次记录是否黑白相间的情况。

转移需要把所有上面的层合并,讨论一些情况。

时间复杂度 (O(nlog n))

CO int N=110;
int n;
namespace seg{
	pair<int,int> val[4*N];
	
	#define lc (x<<1)
	#define rc (x<<1|1)
	#define mid ((l+r)>>1)
	void build(int x,int l,int r){
		if(l==r) {val[x]={read<int>(),l}; return;}
		build(lc,l,mid),build(rc,mid+1,r);
		val[x]=min(val[lc],val[rc]);
	}
	pair<int,int> query(int x,int l,int r,int ql,int qr){
		if(ql<=l and r<=qr) return val[x];
		if(qr<=mid) return query(lc,l,mid,ql,qr);
		if(ql>mid) return query(rc,mid+1,r,ql,qr);
		return min(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
	}
	#undef lc
	#undef rc
	#undef mid
}

int num,L[N],R[N],H[N];
vector<int> to[N];

int build(int l,int r){
	int x=++num;
	L[x]=l,R[x]=r,H[x]=seg::query(1,1,n,l,r).first;
	vector<int> pos;
	for(int i=l;i<=r;){
		pair<int,int> v=seg::query(1,1,n,i,r);
		if(v.first>H[x]) break;
		pos.push_back(v.second);
		i=v.second+1;
	}
	pos.push_back(r+1);
	int last=l-1;
	for(int now:pos){
		if(last+1<=now-1){
			to[x].push_back(build(last+1,now-1));
			H[to[x].back()]-=H[x];
		}
		last=now;
	}
	return x;
}

int F[N][2],coef=1;

void dfs(int x){
//	cerr<<x<<" "<<L[x]<<" "<<R[x]<<" H="<<H[x]<<endl;
	int len=R[x]-L[x]+1;
	for(int y:to[x]) dfs(y),len-=R[y]-L[y]+1;
	F[x][0]=fpow(2,len),F[x][1]=2;
	for(int y:to[x]){
		F[x][0]=mul(F[x][0],add(F[y][0],mul(2,F[y][1])));
		F[x][1]=mul(F[x][1],F[y][1]);
	}
	F[x][0]=add(F[x][0],mod-F[x][1]);
	F[x][1]=mul(F[x][1],fpow(2,H[x]-1));
//	cerr<<x<<" F="<<F[x][0]<<" "<<F[x][1]<<endl;
}

int main(){
	read(n);
	seg::build(1,1,n);
	int root=build(1,n);
	dfs(root);
	int ans=add(F[root][0],F[root][1]);
	ans=mul(ans,coef);
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/12698000.html