【TSINSEN-A1483】方格取数【DP】【随机数据】【单调栈】

2013年集训队论文题。


看了题解后我是大写的懵逼。


(这OJ竟然还有代码风格分)


/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;

const int maxn = 200005, maxlogn = 505;
const LL inf = 0x3f3f3f3f3f3f3f3f;

int n;
int al[maxn], ar[maxn], bl[maxn], br[maxn], A[maxn], B[maxn];
LL suma[maxn], sumb[maxn], dp[maxlogn][maxlogn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

int sta[maxn];

void calc(int *x, int *L, int *R) {
	int top;
	for(int i = 1; i <= n; i++) L[i] = 0, R[i] = n + 1;
	
	top = 0;
	for(int i = 1; i <= n; i++) {
		for(; top && x[i] <= x[sta[top]]; top--) R[sta[top]] = i;
		sta[++top] = i;
	}

	top = 0;
	for(int i = n; i >= 1; i--) {
		for(; top && x[i] <= x[sta[top]]; top--) L[sta[top]] = i;
		sta[++top] = i;
	}
}

int X[maxn], Y[maxn];

inline LL solve(int x1, int y1, int x2, int y2) {
	int topx = 0, topy = 0;
	for(int i = x1; i <= x2; i = br[i]) X[++topx] = i;
	for(int i = x2; i >= x1; i = bl[i]) X[++topx] = i;
	for(int i = y1; i <= y2; i = ar[i]) Y[++topy] = i;
	for(int i = y2; i >= y1; i = al[i]) Y[++topy] = i;
	sort(X + 1, X + topx + 1);
	topx = unique(X + 1, X + topx + 1) - (X + 1);
	sort(Y + 1, Y + topy + 1);
	topy = unique(Y + 1, Y + topy + 1) - (Y + 1);

	for(int i = 1; i <= topx; i++)	for(int j = 1; j <= topy; j++) {
		if(i == 1 && j == 1) {
			dp[i][j] = (LL)A[Y[i]] * B[X[j]];
			continue;
		}
		LL ans1 = inf, ans2 = inf;
		if(j != 1) ans1 = dp[i][j - 1] + (LL)B[X[i]] * (suma[Y[j]] - suma[Y[j - 1]]);
		if(i != 1) ans2 = dp[i - 1][j] + (LL)A[Y[j]] * (sumb[X[i]] - sumb[X[i - 1]]);
		dp[i][j] = min(ans1, ans2);
	}

	return dp[topx][topy];
}

int main() {
	n = iread(); int T = iread();
	for(int i = 1; i <= n; i++) suma[i] = suma[i - 1] + (A[i] = iread()); calc(A, al, ar);
	for(int i = 1; i <= n; i++) sumb[i] = sumb[i - 1] + (B[i] = iread()); calc(B, bl, br);
	while(T--) {
		int x1 = iread(), y1 = iread(), x2 = iread(), y2 = iread();
		swap(x1, y1); swap(x2, y2);
		printf("%lld\n", solve(x1, y1, x2, y2));
	}
	return 0;
}


你可能感兴趣的:(dp,单调栈,随机数据)