Y
K
N
U
F

U604938 你不准卡 O(n sqrt n log L) 其中 L log L = sqrt n

U604938 你不准卡 O(n sqrt n log L) 其中 L log L = sqrt n

如题目所言,这道题的出现就是为此,所以不要说什么 wyy。

空间上卡掉了 \(n\sqrt n\) 空间的做法,再有什么我也没法了,就这样。

如果你要卡常

请确保您是 \((O(n\sqrt n \log L),其中L \log L = \sqrt n)\) 或更优的复杂度!!!

  1. 试试 c++23 O2
  2. inlinestatic,快读。
  3. 莫队奇偶性排序。
  4. 读入大数字用 scanf 比快读快。
  5. 少写函数,哪怕 inline,都扔主函数里。
  6. 数组的定义顺序和数组大小也会影响时间。
  7. 不行就抄吧,也许是码风问题。

同复杂度通过的其他题目(标 * 为卡常)

*Rmq Problem / mex
faebdc 的烦恼

正文

首先这是个区间问题显然可以用莫队来做,然后就是要维护区间特定值域内最小众数,按理来讲有很多办法可以维护,但是就是要用线段树!!!

考虑用权值线段树,维护每一个值出现的次数,然后维护最大次数以及其值,结合动态开点显然可以做到 \(O(\log V)\) 的修改和查询。

但是过不了呢!

考虑离散化,这个也显然,可以做到 \(O(\log n)\) 的修改和查询。

还是过不了呢!!

考虑到查询很少,修改很多,可以稍微平衡一下两者,对值域分块,每一个块使用一个线段树维护,可以做到 \(O(\log \sqrt n)\) 修改,\(O(\sqrt n)\) 查询,已经很优秀了的!

就是过不了哦!!!

我所追求的,是真正的平衡;(好中二,算了)
显然修改次数是 \(n\sqrt n\) 的,查询次数是 \(n\) 的,上一步我们已经平衡了一部分,但是还不够,设值域分块中线段树的长度为 \(L\),容易得到两种操作的总复杂度分别为 \(O(n\sqrt n \log L)\)\(O(n\frac nL)\),强行将两者调平,得到 \(L\log L=\sqrt n\) 时复杂度最优秀。

不过,这依然无法!……好吧过了。(原来是过不了的,后来仁慈了)

其实不要仅停留在理论,两个式子是有着隐藏的系数的,没错,就是常数。大概是这样的 \(O(n\sqrt n \log L \times (线段树大常数))\)\(O(n\frac nL \times(分块跑不满小常数))\),所以显然 \(L\) 要比上面理论算出来的要更小一些才行。

最后再来重申一遍我们的复杂度!!!

\(\Large O(n\sqrt n \log L),其中(L \log L = \sqrt n)!!!\)

代码

// code by 樓影沫瞬_Hz17
#include <bits/stdc++.h>
#define en_ putchar_unlocked('\n')
#define e_ putchar_unlocked(' ')
using namespace std;
inline int in() { 
    int n = 0; char p = getchar_unlocked();
    while (p < '-') p = getchar_unlocked();
	bool f = p == '-' ? p = getchar_unlocked() : 0;
    do n = n * 10 + (p ^ 48), p = getchar_unlocked();
    while (p >= '0');
    return f ? -n : n;
}
inline int in(int &a) { return a = in(); }
inline void out(int n) {
    if(n < 0) putchar_unlocked('-'), n = -n;
	if(n > 9) out(n / 10);
    putchar_unlocked(n % 10 + '0');
}
constexpr int N = 2e5 + 10, B1 = 400, B2 = 50;
using pii = pair<int, int>;
 
int ls[N * 4], rs[N * 4], mx[N * 4], id[N * 4];

struct Query {
	int l, r, L, R, id;
} q[N];

int a[N], hs[N], pos1[N], pos2[N];

int rt[3010], L[3010], R[3010], cnt, n, cntv;

inline void build(int &u, const int l, const int r) {
	u = ++ cnt;
	if(l == r) { 
		id[u] = l;
		return;
	}
	int m = (l + r) >> 1;
	build(ls[u], l, m);
	build(rs[u], m + 1, r);
	mx[u] = mx[ls[u]], id[u] = id[ls[u]];
}

inline void update(const int u, const int l, const int r, const int p) {
	if(l == r) {
		++ mx[u];
		return;
	}
	int m = (l + r) >> 1;
	if(p <= m) update(ls[u], l, m, p);
	if(p > m) update(rs[u], m + 1, r, p);
	if(mx[ls[u]] >= mx[rs[u]]) {
		mx[u] = mx[ls[u]], id[u] = id[ls[u]];
		return;
	}
	mx[u] = mx[rs[u]], id[u] = id[rs[u]];
}

inline void reduce(const int u, const int l, const int r, const int p) {
	if(l == r) {
		-- mx[u];
		return;
	}
	int m = (l + r) >> 1;
	if(p <= m) reduce(ls[u], l, m, p);
	if(p > m) reduce(rs[u], m + 1, r, p);
	if(mx[ls[u]] >= mx[rs[u]]) {
		mx[u] = mx[ls[u]], id[u] = id[ls[u]];
		return;
	}
	mx[u] = mx[rs[u]], id[u] = id[rs[u]];
}

inline pii query(const int u, const int l, const int r, const int L, const int R) {
	if(L > r || l > R) return {0, 0};
	if(L <= l and r <= R) return {mx[u], id[u]};
	int m = (l + r) >> 1;
	pii t1 = query(ls[u], l, m, L, R), t2 = query(rs[u], m +1, r, L, R);
	return t1.first >= t2.first ? t1 : t2;
}

int ans[N];

signed main() {
	#ifndef ONLINE_JUDGE 
		freopen("5.in", "r", stdin);
		freopen("5.out", "w", stdout);
	#endif
	in(n);
	for(int i = 1; i <= n; i ++) hs[i] = in(a[i]);
	for(int i = 1; i <= n; i ++) 
		in(q[i].l), in(q[i].r), in(q[i].L), in(q[i].R), q[i].id = i, pos1[i] = (i - 1) / B1 +1;
	
	for(int i = 1; R[i - 1] != n; i ++) {
		L[i] = (i - 1) * B2 + 1, R[i] = min(i * B2, n);
		for(int j = L[i]; j <= R[i]; j ++) pos2[j] = i;
		build(rt[i], L[i], R[i]);
	}
	sort(q + 1, q + 1 + n, [](const Query &a, const Query &b) 
		{ return pos1[a.l] == pos1[b.l] ? pos1[a.l] & 1 ? a.r < b.r : a.r > b.r : pos1[a.l] < pos1[b.l];});

	sort(hs + 1, hs + 1 + n);
	int len = unique(hs + 1, hs + 1+ n) - hs - 1;
	for(int i = 1; i <= n; i ++) {
		a[i] = lower_bound(hs + 1, hs + len + 1, a[i]) - hs;
		q[i].L = lower_bound(hs + 1, hs + len + 1, q[i].L) - hs;
		q[i].R = lower_bound(hs + 1, hs + len + 1, q[i].R) - hs;
	}
	
	for(int i = 1, l = 1, r = 0, ql, qr, ID, MX; i <= n; i ++) {
		while(l < q[i].l) reduce(rt[pos2[a[l]]], L[pos2[a[l]]], R[pos2[a[l]]], a[l]), ++ l;
		while(l > q[i].l) -- l, update(rt[pos2[a[l]]], L[pos2[a[l]]], R[pos2[a[l]]], a[l]);
		while(r < q[i].r) ++ r, update(rt[pos2[a[r]]], L[pos2[a[r]]], R[pos2[a[r]]], a[r]);
		while(r > q[i].r) reduce(rt[pos2[a[r]]], L[pos2[a[r]]], R[pos2[a[r]]], a[r]), -- r;

		ql = pos2[q[i].L], qr = pos2[q[i].R], MX = 0, ID = 0;
		if(ql != qr) {
			pii t = query(rt[ql], L[ql], R[ql], q[i].L, R[ql]);
			if(t.first > MX) MX = t.first, ID = t.second;
			for(int i = ql + 1; i < qr; i ++) 
				if(mx[rt[i]] > MX) MX = mx[rt[i]], ID = id[rt[i]];
			t = query(rt[qr], L[qr], R[qr], L[qr], q[i].R);
			if(t.first > MX) MX = t.first, ID = t.second;
		}
		if(ql == qr) {
			pii t = query(rt[ql], L[ql], R[ql], q[i].L, q[i].R);
			if(t.first) ID = t.second;
		}
		ans[q[i].id] = ID;
	}

	for(int i = 1; i <= n; i ++) {
		if(!ans[i]) putchar_unlocked('-');
		if(ans[i]) out(hs[ans[i]]);
		en_;
	}
} 
// 星間~ 干渉~ 融解~ 輪迴~ 邂逅~ 再生~ ララバイ~
posted @ 2025-09-11 21:56  樓影沫瞬_17Hz  阅读(17)  评论(0)    收藏  举报