LY1099 [ 20230222 CQYC模拟赛 T2 ] 相似序列

发布时间 2023-12-25 21:49:26作者: cxqghzj

题意

给定一个序列。

每次询问求两个区间排序后是否只有一个或者没有位置不同。

Sol

不难想到主席树维护值域。

考虑如何判断。

注意到当前答案正确,当且仅当值域上两点不同且相邻。

维护每个点的哈希值判断即可。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
	int p = 0, flg = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') flg = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		p = p * 10 + c - '0';
		c = getchar();
	}
	return p * flg;
}
void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	if (x > 9) {
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

const int N = 1e5 + 5;

array <int, N> idx;

namespace Sgt {

array <int, N * 800> lc, rc;
array <int, N * 800> edge;
int cnt;

void pushup(int x) {
	edge[x] = edge[lc[x]] + edge[rc[x]];
}

void modify(int &x, int l, int r, int y) {
	cnt++;
	lc[cnt] = lc[x];
	rc[cnt] = rc[x];
	edge[cnt] = edge[x];
	x = cnt;
	if (l == r) {
		edge[x] += idx[y];
		return;
	}
	int mid = (l + r) >> 1;
	if (y <= mid) modify(lc[x], l, mid, y);
	else modify(rc[x], mid + 1, r, y);
	pushup(x);
}

int query(int x1, int x2, int l, int r, int L, int R) {
	if (L > r || R < l) return 0;
	if (L <= l && R >= r) return (edge[x1] - edge[x2]);
	int mid = (l + r) >> 1, ans = 0;
	if (L <= mid) ans += query(lc[x1], lc[x2], l, mid, L, R);
	if (R > mid) ans += query(rc[x1], rc[x2], mid + 1, r, L, R);
	return ans;
}

}

array <int, N> rot;

signed main() {
#ifdef ONLINE_JUDGE
	freopen("similar.in", "r", stdin);
	freopen("similar.out", "w", stdout);
#endif
	int n = read(), q = read();
	idx[0] = 1;
	for (int i = 1; i <= 1e5; i++)
		idx[i] = idx[i - 1] * 131ll;
	for (int i = 1; i <= n; i++) {
		int x = read();
		rot[i] = rot[i - 1];
		Sgt::modify(rot[i], 1, 1e5, x);
	}
	while (q--) {
		int x_1 = read(), y_1 = read(), x_2 = read(), y_2 = read();
		int tp1, tp2;
		if ((tp1 = Sgt::query(rot[y_1], rot[x_1 - 1], 1, 1e5, 1, 1e5)) ==
			(tp2 = Sgt::query(rot[y_2], rot[x_2 - 1], 1, 1e5, 1, 1e5))) {
			puts("YES");
			continue;
		}
		/* cout << tp1 << " " << (int)tp2 << endl; */
		int l = 1, r = 1e5 + 1, itl = 0;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (Sgt::query(rot[y_1], rot[x_1 - 1], 1, 1e5, 1, mid) ==
				Sgt::query(rot[y_2], rot[x_2 - 1], 1, 1e5, 1, mid))
				itl = mid, l = mid + 1;
			else
				r = mid - 1;
		}
		l = 1, r = 1e5 + 1;
		int itr = 0;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (Sgt::query(rot[y_1], rot[x_1 - 1], 1, 1e5, mid, 1e5) ==
				Sgt::query(rot[y_2], rot[x_2 - 1], 1, 1e5, mid, 1e5))
				itr = mid, r = mid - 1;
			else
				l = mid + 1;
		}

		itl += 2, itr -= 2;
		/* write(itl), putchar(32); */
		/* write(itr), puts(""); */
		if (!Sgt::query(rot[y_1], rot[x_1 - 1], 1, 1e5, itl, itr) &&
			!Sgt::query(rot[y_2], rot[x_2 - 1], 1, 1e5, itl, itr))
			puts("YES");
		else
			puts("NO");

	}
	return 0;
}