题意
有
n
n
n 个数
{
a
i
}
\{a_i\}
{ai},有
m
m
m 个询问,每个询问给定
l
1
,
r
1
,
l
2
,
r
2
l_1,r_1,l_2,r_2
l1,r1,l2,r2,设
{
b
i
}
\{b_i\}
{bi} 为
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1] 排完序后的数组,
{
c
i
}
\{c_i\}
{ci} 为
[
l
2
,
r
2
]
[l_2,r_2]
[l2,r2] 排完序后的数组,问两个数组中是否至多有一位不同。
其中,
n
,
m
,
a
i
≤
1
0
5
n,m,a_i\leq 10^5
n,m,ai≤105。
分析
先将
a
i
a_i
ai 进行哈希,得到
v
a
i
v_{a_i}
vai,假如
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1] 和
[
l
2
,
r
2
]
[l_2,r_2]
[l2,r2] 完全相同,那么
∑
i
=
l
1
r
1
v
a
i
=
∑
i
=
l
2
r
2
v
a
i
\sum\limits_{i=l_1}^{r_1}v_{a_i}=\sum\limits_{i=l_2}^{r_2}v_{a_i}
i=l1∑r1vai=i=l2∑r2vai。
然后我们用主席树维护哈希值,每个节点的值为哈希值的和。假如有一个不同,我们可以在主席树上二分得到第一个不同的数
p
p
p 和最后一个不同的数
q
q
q。
那么排完序后这两个数组相同的条件就是
p
,
q
p,q
p,q 的个数分别相差
1
1
1 且
[
p
+
1
,
q
−
1
]
[p+1,q-1]
[p+1,q−1] 中没有数存在于
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1] 和
[
l
2
,
r
2
]
[l_2,r_2]
[l2,r2] 中。为啥呢? 因为 我们已经比较了
[
1
,
p
]
[1,p]
[1,p] 和
[
q
+
1
,
m
a
x
n
]
[q+1,maxn]
[q+1,maxn]。要保证
p
p
p 和
q
q
q 在可以两个数组的同一位,只需要保证两个数之间没有多的数即可,否则他们不可能在两个数组的同一位。(这里可能需要好好捋一捋)
复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
代码如下
#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define lson l, m, lch[rt]
#define rson m + 1, r, rch[rt]
#define int unsigned long long
#define N 100005
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
LL z = 1;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int ksm(int a, int b, int p){
int s = 1;
while(b){
if(b & 1) s = z * s * a % p;
a = z * a * a % p;
b >>= 1;
}
return s;
}
mt19937_64 rdn(time(0));
int lch[N * 30], rch[N * 30], s[N], sum[N * 30], root[N], v[N], a[N], cnt, maxn = N - 5;
void clr(){
cnt = 0;
memset(lch, 0, sizeof(lch));
memset(rch, 0, sizeof(rch));
memset(sum, 0, sizeof(sum));
memset(root, 0, sizeof(root));
memset(v, 0, sizeof(v));
}
void build(int l, int r, int &rt){
rt = ++cnt;
if(l == r) return;
int m = l + r >> 1;
build(lson);
build(rson);
}
void update(int l, int r, int &rt, int las, int p){
rt = ++cnt;
sum[rt] = sum[las] + v[p];
lch[rt] = lch[las], rch[rt] = rch[las];
if(l == r) return;
int m = l + r >> 1;
if(p <= m) update(lson, lch[las], p);
else update(rson, rch[las], p);
}
int q1(int l, int r, int r1, int r2, int r3, int r4){
if(l == r) return l;
int m = l + r >> 1;
if(sum[lch[r1]] - sum[lch[r2]] != sum[lch[r3]] - sum[lch[r4]]) return q1(l, m, lch[r1], lch[r2], lch[r3], lch[r4]);
return q1(m + 1, r, rch[r1], rch[r2], rch[r3], rch[r4]);
}
int q2(int l, int r, int r1, int r2, int r3, int r4){
if(l == r) return l;
int m = l + r >> 1;
if(sum[rch[r1]] - sum[rch[r2]] != sum[rch[r3]] - sum[rch[r4]]) return q2(m + 1, r, rch[r1], rch[r2], rch[r3], rch[r4]);
return q2(l, m, lch[r1], lch[r2], lch[r3], lch[r4]);
}
int qsum(int l, int r, int rt, int las, int a, int b){
if(l >= a && r <= b) return sum[rt] - sum[las];
int m = l + r >> 1, ans = 0;
if(a <= m) ans += qsum(lson, lch[las], a, b);
if(b > m) ans += qsum(rson, rch[las], a, b);
return ans;
}
int gs(int l, int r, int x, int y){
if(x > y) return 0;
return qsum(1, maxn, root[r], root[l - 1], x, y);
}
main(){
int i, j, n, m, t, T, l, r, x, y, p, q, w1, w2, w3, w4;
T = read();
while(T--){
clr();
n = read(); m = read();
for(i = 1; i <= n; i++) a[i] = read();
for(i = 1; i <= maxn; i++) v[i] = rdn();
for(i = 1; i <= n; i++) s[i] = s[i - 1] + v[a[i]];
build(1, maxn, root[0]);
for(i = 1; i <= n; i++) update(1, maxn, root[i], root[i - 1], a[i]);
for(i = 1; i <= m; i++){
l = read(); r = read(); x = read(); y = read();
if(s[r] - s[l - 1] == s[y] - s[x - 1]) printf("YES\n");
else{
p = q1(1, maxn, root[r], root[l - 1], root[y], root[x - 1]);
q = q2(1, maxn, root[r], root[l - 1], root[y], root[x - 1]);
w1 = gs(l, r, p, p) - gs(x, y, p, p); w2 = gs(l, r, q, q) - gs(x, y, q, q);
w3 = gs(l, r, p + 1, q - 1), w4 = gs(x, y, p + 1, q - 1);
if(((w1 == v[p] && w2 + v[q] == 0) || (w2 == v[q] && w1 + v[p] == 0)) && w3 == 0 && w4 == 0) printf("YES\n");
else printf("NO\n");
}
}
}
return 0;
}
/*
1
6 5
1 3 4 2 3 4
1 3 4 6
2 5 3 6
*/