LG3120 [USACO15FEB]Cow Hopscotch G CDQ分治维护DP顺序

题目描述

传送门

题解

容易得到转移方程 \(dp(i,j)=\sum\limits_{x=1}^{i-1}{\sum\limits_{y=1}^{j-1}{dp(x,y)|a_{i,j} \neq a_{x,y}}}\)

边界条件为 \(dp(1,1) = 1\)

然后呢,人傻了,这东西转移条件非常苛刻,都是严格小于。

人傻数据结构来凑,写个线段树套线段树吧

人又傻了,不会树套树啊。

于是可以 cdq 分治维护 dp 顺序

看这两个限制条件

\(\begin{cases} x<i\\ y<j \end{cases}\)

是一个二维偏序问题,可以强上 cdq 压掉一维。

然后就傻逼题了。

代码

#include<bits/stdc++.h>
using namespace std;

template < typename Tp >
inline void read(Tp &x) {
	x = 0; int fh = 1; char ch = 1;
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') fh = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	x *= fh;
}

template < typename Tp >
inline void biread(Tp &x) {
	x = 0; int fh = 1; char ch = 1;
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') fh = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') x = x * 2 + ch - '0', ch = getchar();
	x *= fh;
}

const int mod = 1000000007;

int n, m, k;
int s[750 * 750 + 7];
int dp[757][757], a[757][757];

void cdq(int l, int r) {
	if(l == r) return ;
	int mid = (l + r) >> 1;
	cdq(l, mid);
	int total = 0;
	for(int i = 1; i <= m; i++) {
		for(int j = mid + 1; j <= r; j++) {
			dp[i][j] = ((dp[i][j] + total - s[a[i][j]]) % mod + mod) % mod;
		}
		for(int j = l; j <= mid; j++) {
//			dp[i][j] = (dp[i][j] + total - s[a[i][j]]) % mod;
			s[a[i][j]] = (s[a[i][j]] + dp[i][j]) % mod;
			total = (total + dp[i][j]) % mod;
		}
	}
	for(int i = 1; i <= m; i++) {
		for(int j = l; j <= mid; j++) s[a[i][j]] = ((s[a[i][j]] - dp[i][j]) % mod + mod) % mod;
	}
	cdq(mid + 1, r);
}

inline void Init(void) {
	read(n); read(m); read(k);
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			read(a[i][j]);
		}
	}
}

inline void Work(void) {
	dp[1][1] = 1;
	cdq(1, n);
	printf("%d\n", dp[n][m]);
}

signed main(void) {
	Init();
	Work();
	return 0;
}
posted @ 2020-10-22 14:18  览遍千秋  阅读(129)  评论(0编辑  收藏  举报