MnZn 回滚莫队模板 22pts 求调
查看原帖
MnZn 回滚莫队模板 22pts 求调
1033727
toolazy楼主2024/4/24 21:00

上强度了,过了样例,但是其它的只过了 #1 #2 #3 和 #17(最后一个点),剩下的全 WA。

调很久了,感觉莫队的框架和细节都没什么问题。讨论区全部都翻了一遍,他们的 hack 都过了,他们说到的点我好像也都没什么问题(有些看不太懂不知道对没对上 qwq)。

思路是存区间内每种颜色的最左(mn)和最右(mx),每次扩展的时候,更新答案就两边都减一下比比,然后再来更新 mn 和 mx。

L 是左端点,R 是右端点,ans 是答案。用到的变量都开了 [2] 的数组,下标为 #define NOW 0 为现在使用的变量们,反过来 #define PRE 1 就是记录下来用来回滚的。

还求 dalao 们救急!调三五天了怎么调都调不出来 qwq,bdfs 也什么都查不到,要枯了(蔫

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int MAXN = 2e5 + 5;

int n, m, c[MAXN];

namespace DSC {
	
	struct sblzl {
		
		int v, idx;
		
	} a[MAXN];
	
	void dsc() {
		// 离散化应该没问题
		cin >> n;
		for (int i = 1; i <= n; a[i].idx = i, i ++)
			cin >> a[i].v;
		sort(a + 1, a + 1 + n, [](sblzl a, sblzl b) {
			return a.v < b.v;
		});
		for (int i = 1, lastv = 0, level = 0; i <= n; i ++) {
			level += (a[i].v != lastv);
			lastv = a[i].v;
			a[i].v = level;
		}
		sort(a + 1, a + 1 + n, [](sblzl a, sblzl b) {
			return a.idx < b.idx;
		});
		for (int i = 1; i <= n; i ++)
			c[i] = a[i].v;
//			cout << (c[i] = a[i].v) << ' ';
	}
	
}

namespace LRZmustWin {
	
#define NOW 0
#define PRE 1
	
#define sqrt __builtin_sqrt
	
	int mn[2][MAXN], mx[2][MAXN], L[2], R[2], ans[2], blen;
	
	struct Q {
		
		int l, r, f, idx;
		
	} query[MAXN];
	
	queue<int> rmQ;
	
	void input() {
		// 读入和排序, 应该没问题
		cin >> m;
		for (int i = 1; i <= m; query[i].idx = i, i ++)
			cin >> query[i].l >> query[i].r;
		blen = sqrt(n);
		sort(query + 1, query + 1 + m, [](Q a, Q b) {
			int aidx = (a.l - 1) / blen + 1;
			int bidx = (b.l - 1) / blen + 1;
			return (aidx != bidx ? aidx < bidx : a.r < b.r);
		});
	}
	
	void add(int idx) {
		int color = c[idx];
		rmQ.push(color);
		if (mn[NOW][color] == 0) {
			mn[NOW][color] = idx;
			mx[NOW][color] = idx;
			return;
		}
		ans[NOW] = max(ans[NOW], max(abs(idx - mn[NOW][color]), abs(idx - mx[NOW][color])));
		mn[NOW][color] = min(mn[NOW][color], idx);
		mx[NOW][color] = max(mx[NOW][color], idx);
	}
	
#define typeROLLBACK NOW
#define typeMEMORY PRE
#define typeCLS 114514
	
	void rollmem(int rollback) {
		if (rollback == typeCLS) {
			while (!rmQ.empty()) {
				int color = rmQ.front();
				rmQ.pop();
				mn[0][color] = mn[1][color] = 0;
				mx[0][color] = mn[1][color] = 0;
			}
			L[0] = L[1] = 1;
			R[0] = R[1] = 0;
			ans[0] = ans[1] = 0;
			return;
		}
		while (!rmQ.empty()) {
			int color = rmQ.front();
			rmQ.pop();
			mn[rollback][color] = mn[!rollback][color];
			mx[rollback][color] = mx[!rollback][color];
		}
		L[rollback] = L[!rollback];
		R[rollback] = R[!rollback];
		ans[rollback] = ans[!rollback];
	}
	
	void solve() {
		int queryidx = 1;
		for (int blockLimit = blen; queryidx <= m; blockLimit += blen) {
			// 先处理同块的小问题
			rollmem(typeCLS);
			while (queryidx <= m && query[queryidx].r <= blockLimit) {
				for (int i = query[queryidx].l; i <= query[queryidx].r; i ++)
					add(i);
				query[queryidx ++].f = ans[NOW];
				rollmem(typeCLS);
			}
			// 再来正常处理所有的
			L[NOW] = blockLimit + 1, R[NOW] = blockLimit;
			while (queryidx <= m && query[queryidx].l <= blockLimit) {
				while (R[NOW] < query[queryidx].r)
					add(++ R[NOW]);
				rollmem(typeMEMORY);
				while (L[NOW] > query[queryidx].l)
					add(-- L[NOW]);
				query[queryidx ++].f = ans[NOW];
				rollmem(typeROLLBACK);
			}
		}
	}
	
	void print() {
		// 输出, 应该没问题
		sort(query + 1, query + 1 + m, [](Q a, Q b) {
			return a.idx < b.idx;
		});
		for (int i = 1; i <= m; i ++)
			cout << query[i].f << '\n';
	}
	
}

int main() {
	// 这里应该就没问题了...
	ios :: sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	DSC :: dsc();
	LRZmustWin :: input();
	LRZmustWin :: solve();
	LRZmustWin :: print();
	return 0;
}

感激不尽!(磕

2024/4/24 21:00
加载中...