对权值建主席树 然后对于区间[a,b],[c,d]
在主席树上二分排完序后从左第一个不一样的地方 以及从右第一个不一样的地方
这个可以Hash下权值的出现次数,也是可以相减的
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=100005;
const int M=10000005;
const int maxn=1e5;
int rt[N],ncnt;
int ls[M],rs[M];
ull H[M]; int sum[M];
ull seed[N];
inline void add(int &x,int y,int l,int r,int t){
x=++ncnt;
if (l==r){
sum[x]=sum[y]+1; H[x]=sum[x]; return;
}
int mid=(l+r)>>1;
if (t<=mid) add(ls[x],ls[y],l,mid,t),rs[x]=rs[y];
else add(rs[x],rs[y],mid+1,r,t),ls[x]=ls[y];
H[x]=H[ls[x]]+seed[mid-l+1]*H[rs[x]];
sum[x]=sum[ls[x]]+sum[rs[x]];
}
int Ret=0;
inline void queryL(int a,int b,int c,int d,int l,int r){
if (H[b]-H[a]==H[d]-H[c]){ Ret+=sum[b]-sum[a]; return; }
if (l==r){
Ret+=min(sum[b]-sum[a],sum[d]-sum[c]);
return;
}
int mid=(l+r)>>1;
if (H[ls[b]]-H[ls[a]]==H[ls[d]]-H[ls[c]]){
Ret+=sum[ls[b]]-sum[ls[a]];
queryL(rs[a],rs[b],rs[c],rs[d],mid+1,r);
}else
queryL(ls[a],ls[b],ls[c],ls[d],l,mid);
}
inline void queryR(int a,int b,int c,int d,int l,int r){
if (H[b]-H[a]==H[d]-H[c]){ Ret+=sum[b]-sum[a]; return; }
if (l==r){
Ret+=min(sum[b]-sum[a],sum[d]-sum[c]);
return;
}
int mid=(l+r)>>1;
if (H[rs[b]]-H[rs[a]]==H[rs[d]]-H[rs[c]]){
Ret+=sum[rs[b]]-sum[rs[a]];
queryR(ls[a],ls[b],ls[c],ls[d],l,mid);
}else
queryR(rs[a],rs[b],rs[c],rs[d],mid+1,r);
}
int n,val[N];
int main(){
int T;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(T); seed[0]=1; for (int i=1;i<=maxn;i++) seed[i]=seed[i-1]*233333;
while (T--){
ncnt=0; int Q,a,b,c,d;
read(n); read(Q);
for (int i=1;i<=n;i++)
read(val[i]),add(rt[i],rt[i-1],1,maxn,val[i]);
while (Q--){
read(a); read(b); read(c); read(d);
int lret,rret;
Ret=0;
queryL(rt[a-1],rt[b],rt[c-1],rt[d],1,maxn);
lret=Ret;
Ret=0;
queryR(rt[a-1],rt[b],rt[c-1],rt[d],1,maxn);
rret=Ret;
if ((lret==b-a+1) || (lret+rret+1==b-a+1))
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}