Solution - P2254 [NOI2005] 瑰丽华尔兹

竟然是《海上钢琴师》啊啊啊

以前做 P1725 琪露诺 的时候想过把这题升维会怎么样,没想到还真见到了。

思路

就是一个 DP + 一堆单调队列。

实现参考琪露诺,按移动方向打 DP 就行了。注意遇到障碍的时候清队列,还有维护单调性的时候考虑偏移量。

于是,没了。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 205 
#define inf 1000000007
using namespace std;

char a[N][N];
int dp[2][N][N];
int que[N], he, ta;
int n, m, k, x, y, ans;

#define clear(nt) for(rint i = 1; i <= n; ++i) for(rint j = 1; j <= m; ++j) dp[nt][i][j] = -inf;

inline void trans1(rint nt, rint x, rint t){
	rint lt = !nt;
	he = 1, ta = 0;
	for(rint i = n; i >= 1; --i){
		if(a[i][x] == 'x'){he = 1, ta = 0; continue;}
		if(dp[lt][i][x] >= 0){
			while(ta >= he && dp[lt][que[ta]][x]+(que[ta]-i) <= dp[lt][i][x]) --ta;
			que[++ta] = i;
		}
		if(ta >= he) dp[nt][i][x] = dp[lt][que[he]][x]+(que[he]-i);
		while(ta >= he && que[he]-i >= t) ++he;
	}
}

inline void trans2(rint nt, rint x, rint t){
	rint lt = !nt;
	he = 1, ta = 0;
	for(rint i = 1; i <= n; ++i){
		if(a[i][x] == 'x'){he = 1, ta = 0; continue;}
		if(dp[lt][i][x] >= 0){
			while(ta >= he && dp[lt][que[ta]][x]+(i-que[ta]) <= dp[lt][i][x]) --ta;
			que[++ta] = i;
		}
		if(ta >= he) dp[nt][i][x] = dp[lt][que[he]][x]+(i-que[he]);
		while(ta >= he && i-que[he] >= t) ++he;
	}
}

inline void trans3(rint nt, rint x, rint t){
	rint lt = !nt;
	he = 1, ta = 0;
	for(rint i = m; i >= 1; --i){
		if(a[x][i] == 'x'){he = 1, ta = 0; continue;}
		if(dp[lt][x][i] >= 0){
			while(ta >= he && dp[lt][x][que[ta]]+(que[ta]-i) <= dp[lt][x][i]) --ta;
			que[++ta] = i;
		}
		if(ta >= he) dp[nt][x][i] = dp[lt][x][que[he]]+(que[he]-i);
		while(ta >= he && que[he]-i >= t) ++he;
	}
}

inline void trans4(rint nt, rint x, rint t){
	rint lt = !nt;
	he = 1, ta = 0;
	for(rint i = 1; i <= m; ++i){
		if(a[x][i] == 'x'){he = 1, ta = 0; continue;}
		if(dp[lt][x][i] >= 0){
			while(ta >= he && dp[lt][x][que[ta]]+(i-que[ta]) <= dp[lt][x][i]) --ta;
			que[++ta] = i;
		}
		if(ta >= he) dp[nt][x][i] = dp[lt][x][que[he]]+(i-que[he]);
		while(ta >= he && i-que[he] >= t) ++he;
	}
}

int main(){
	scanf("%d %d %d %d %d", &n, &m, &x, &y, &k);
	for(rint i = 1; i <= n; ++i)
		scanf("%s", a[i]+1);
	clear(0);
	dp[0][x][y] = 0;
	for(rint i = 1; i <= k; ++i){
		rint l, r, op;
		rint nt = i&1, lt = ~i&1;
		scanf("%d %d %d", &l, &r, &op);
		clear(nt);
		if     (op == 1) for(rint i = 1; i <= m; ++i) trans1(nt, i, r-l+1);
		else if(op == 2) for(rint i = 1; i <= m; ++i) trans2(nt, i, r-l+1);
		else if(op == 3) for(rint i = 1; i <= n; ++i) trans3(nt, i, r-l+1);
		else             for(rint i = 1; i <= n; ++i) trans4(nt, i, r-l+1);
	} 
	for(rint i = 1; i <= n; ++i)
		for(rint j = 1; j <= m; ++j)
			ans = max(ans, dp[k&1][i][j]);
	printf("%d", ans);
	return 0;
}

posted @ 2025-04-24 20:13  Hootime  阅读(36)  评论(0)    收藏  举报