这里用的是分块的做法。
首先可以差分一下,把左区间都换为1,对一个固定的x
g
e
t
(
l
1
,
r
1
)
∗
g
e
t
(
l
2
,
r
2
)
=
(
g
e
t
(
1
,
r
1
)
−
g
e
t
(
1
,
l
1
−
1
)
)
∗
(
g
e
t
(
1
,
r
2
)
−
g
e
t
(
1
,
l
2
−
1
)
)
=
g
e
t
(
1
,
r
1
)
∗
g
e
t
(
1
,
r
2
)
+
g
e
t
(
1
,
l
1
−
1
)
∗
g
e
t
(
1
,
l
2
−
1
)
−
g
e
t
(
1
,
r
1
)
∗
g
e
t
(
1
,
l
2
−
1
)
−
g
e
t
(
1
,
r
2
)
∗
g
e
t
(
1
,
l
1
−
1
)
get(l1,r1)*get(l2,r2)\\ =(get(1,r1)-get(1,l1-1))*(get(1,r2)-get(1,l2-1))\\ =get(1,r1)*get(1,r2)+get(1,l1-1)*get(1,l2-1)-get(1,r1)*get(1,l2-1)-get(1,r2)*get(1,l1-1)
get(l1,r1)∗get(l2,r2)=(get(1,r1)−get(1,l1−1))∗(get(1,r2)−get(1,l2−1))=get(1,r1)∗get(1,r2)+get(1,l1−1)∗get(1,l2−1)−get(1,r1)∗get(1,l2−1)−get(1,r2)∗get(1,l1−1)
上面能拆开是因为get是线性的。
然后就要处理get(1,p)*get(1,q),分块一下,每块大小N=sqrt(n),在N,2N,3N,……这些位置预处理出区间[1,k*N]中每个数出现的次数。同时可以预处理出get(1,k1*N)*(get1,k2*N)的值。
然后对get(1,p)*get(1,q),找到p,q包含的最大已处理的块(对p,找到最大k*N<=p),剩余部分暴力跑。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef double db;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef pair<long long,int> PLI;
const ll mod=1000000007;
//mt19937_64 mrand(random_device{}());
//int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
int n,_,N;
int a[50066];
int A[250][50066],B[250][50066];
ll w[250][250];
void init()
{
for(int id=1,r=N;r<=n;id++,r=r+N)
{
for(int i=1;i<=r;i++)
{
A[id][a[i]]++;
B[id][a[i]]++;
}
ll W=0;
for(int i=1;i<=n;i++)W+=1ll*A[id][i]*A[id][i];
w[id][id]=W;
for(int i=r+1;i<=n;i++)
{
W+=A[id][a[i]];
if(i%N==0)
{
w[id][i/N]=W;
}
}
}
// for(int i=1;i<=2;i++)
// {
// for(int j=i;j<=2;j++)
// {
// printf("%lld ",w[i][j]);
// }puts("");
// }
}
ll solve(int p,int q)
{
if(p>q)swap(p,q);
if(p==0)return 0;
ll s=(p)/N,t=(q)/N;
ll ret=w[s][t];
for(int i=s*N+1;i<=p;i++)
{
A[s][a[i]]++;
ret+=B[t][a[i]];
}
for(int i=t*N+1;i<=q;i++)
{
ret+=A[s][a[i]];
}
for(int i=s*N+1;i<=p;i++)
{
A[s][a[i]]--;
}
//printf("___%d %d %lld\n",p,q,ret);
return ret;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
N=sqrt(n);
init();
scanf("%d",&_);
while(_--)
{
int l1,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
l1--;l2--;
ll ans=solve(r1,r2)+solve(l1,l2)-solve(l1,r2)-solve(l2,r1);
printf("%lld\n",ans);
}
return 0;
}