社区讨论

求条 WA on 4 8 19

P8818[CSP-S 2022] 策略游戏参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mhj3gf3w
此快照首次捕获于
2025/11/03 20:06
4 个月前
此快照最后确认于
2025/11/03 20:06
4 个月前
查看原帖
注:subtask #1 通过偷窥数据发现是把负数输出成0
CPP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <climits>

namespace noip {
typedef long long Int;

constexpr Int MAX_N = 100000;
constexpr Int MAX_M = 100000;
constexpr Int MAX_LOG_N = 18;
constexpr Int MAX_LOG_M = 18;
constexpr Int MG = LLONG_MAX;	// 美观作用 

Int n, m, q, a[MAX_N+1], b[MAX_M+1];
Int LOG[MAX_N+1];
Int mia[MAX_N+1][MAX_LOG_N+1], maa[MAX_N+1][MAX_LOG_N+1];
Int miaz[MAX_N+1][MAX_LOG_N+1], maaf[MAX_N+1][MAX_LOG_N+1]; // 正数最小和负数最大 
Int mib[MAX_M+1][MAX_LOG_M+1], mab[MAX_M+1][MAX_LOG_M+1];
Int l1, r1, l2, r2, len, ans, ac;

void init() {
	LOG[1] = 0; for (Int i = 2; i <= n; i++) LOG[i] = LOG[i/2] + 1;
	
	for (Int i = 1, e = 0; i <= n; i++) {
		mia[i][e] = a[i];
		maa[i][e] = a[i];
		miaz[i][e] = a[i] <= 0 ? MG : a[i];
		maaf[i][e] = a[i] > 0 ? -MG : a[i];
	}
	
	for (Int e = 1; e <= LOG[n]; e++)
		for (Int i = n; i >= 1; i--)
			if (i+(1<<(e-1)) <= n) {
				mia[i][e] = std::min(mia[i][e-1], mia[i+(1<<(e-1))][e-1]);
				maa[i][e] = std::max(maa[i][e-1], maa[i+(1<<(e-1))][e-1]);
				miaz[i][e] = std::min(miaz[i][e-1], miaz[i+(1<<(e-1))][e-1]);
				maaf[i][e] = std::max(maaf[i][e-1], maaf[i+(1<<(e-1))][e-1]);
			}
			else {
				mia[i][e] = mia[i][e-1];
				maa[i][e] = maa[i][e-1];
				miaz[i][e] = miaz[i][e-1];
				maaf[i][e] = maaf[i][e-1];
			}
			
	
	for (Int i = 1, e = 0; i <= m; i++) {
		mib[i][e] = b[i];
		mab[i][e] = b[i];
	}
	
	for (Int e = 1; e <= LOG[m]; e++)
		for (Int i = m; i >= 1; i--)
			if (i+(1<<(e-1)) <= m) {
				mib[i][e] = std::min(mib[i][e-1], mib[i+(1<<(e-1))][e-1]);
				mab[i][e] = std::max(mab[i][e-1], mab[i+(1<<(e-1))][e-1]);
			}
			else {
				mib[i][e] = mib[i][e-1];
				mab[i][e] = mab[i][e-1];
			}
}

Int ask(Int f[100001][19], Int L, Int R, Int t) {
	len = R-L+1;
	if (t == 1)
		return std::max(f[L][LOG[len]], f[R-(1<<LOG[len])+1][LOG[len]]);
	else
		return std::min(f[L][LOG[len]], f[R-(1<<LOG[len])+1][LOG[len]]);
}

Int bc(Int ac) {
	if (ac > 0) return noip::ask(mib, l2, r2, 2LL);
	else if (ac <= 0) return noip::ask(mab, l2, r2, 1LL);
}
    
void main() {
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	std::cin >> n >> m >> q;
	for (Int i = 1; i <= n; i++) std::cin >> a[i];
	for (Int i = 1; i <= m; i++) std::cin >> b[i];
	
	noip::init(); 
	
	while (q--) {
		std::cin >> l1 >> r1 >> l2 >> r2;
		// 对于 L 来说,自己被资本做局,只能让差异最小化 
		// 由于 L 看得到 Q 的候选范围,故只需要尝试  
		// 最大,最小,非正数最大,正数最小 
		// 去模拟 Q 的回答,然后取一个 max 即可 
		
		// 对于 Q 来说,自己只要根据 L 选的来选就可以
		// 如果 L 选了正数,那么自己选值最小的数 
		// 如果 L 选了非正数,那么自己选值最大的数 
		
		// 对于 A 建立 min负值 max负值 min正值 和 max正值 的 st表 
		// 对于 B 建立 min值 和 max值 的 st表 
		
		ac = noip::ask(mia, l1, r1, 2LL);
		ans = std::max(-MG, ac*noip::bc(ac));
		ac = noip::ask(maa, l1, r1, 1LL);
		ans = std::max(ans, ac*noip::bc(ac));
		ac = noip::ask(miaz, l1, r1, 2LL);
		if (ac != MG) ans = std::max(ans, ac*noip::bc(ac));
		ac = noip::ask(maaf, l1, r1, 1LL);
		if (ac != -MG) ans = std::max(ans, ac*noip::bc(ac));
		
		std::cout << ans << std::endl;
	}
}
} int main() {
	noip::main();
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...