zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    创建smartfroms页格式
    常用TCODE
    CALL transaction 的用法-传内表
    POPUP_TO_CONFIRM的使用方法
    PARAMETERS 指令
    常用弹出对话框函数
    alv界面透视功能
    解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
    Error:java: Annotation processing is not supported for module cycles.
    pom配置进行版本号统一管理
  • 原文地址:https://www.cnblogs.com/autoint/p/12698000.html
Copyright © 2011-2022 走看看