Cow Hopscotch G

题目链接:Cow Hopscotch G


状态以及状态转移方程很显然,故不再赘述。

我们直接考虑转移的优化,我们枚举每一行,然后用线段树维护每一列每一种颜色的方案和。

然后每次就可以从不同的颜色转移而来,不同颜色可以用总方案减去当前颜色方案得到。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e3+10,M=N*N*20,mod=1e9+7;
int n,m,g[N][N],sum[M],lc[M],rc[M],rt[M],cnt,dp[N][N],k;
inline void add(int &x,int y){x+=y; if(x>=mod) x-=mod;}
#define mid (l+r>>1)
void change(int &p,int l,int r,int x,int v){
	if(!p)	p=++cnt;
	if(l==r){add(sum[p],v); return ;}
	if(x<=mid)	change(lc[p],l,mid,x,v);
	else	change(rc[p],mid+1,r,x,v);
	sum[p]=(sum[lc[p]]+sum[rc[p]])%mod;
}
int ask(int p,int l,int r,int ql,int qr){
	if(!p||ql>qr)	return 0;
	if(l==ql&&r==qr)	return sum[p];
	if(qr<=mid)	return ask(lc[p],l,mid,ql,qr);
	else if(ql>mid) return ask(rc[p],mid+1,r,ql,qr);
	else return (ask(lc[p],l,mid,ql,mid)+ask(rc[p],mid+1,r,mid+1,qr))%mod;
}
signed main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)	for(int j=1;j<=n;j++)	cin>>g[i][j];
	change(rt[g[1][1]],1,m,1,1);	change(rt[0],1,m,1,1);
	for(int i=2;i<=n;i++){
		for(int j=2;j<=m;j++)
			dp[i][j]=(ask(rt[0],1,m,1,j-1)-ask(rt[g[i][j]],1,m,1,j-1)+mod)%mod;
		for(int j=2;j<=m;j++)	
			change(rt[g[i][j]],1,m,j,dp[i][j]),change(rt[0],1,m,j,dp[i][j]);
	}
	cout<<dp[n][m];
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107852447