https://vjudge.net/problem/HYSBZ-5016
思路:很明显有
g
e
t
(
l
,
r
,
x
)
=
g
e
t
(
1
,
r
,
x
)
−
g
e
t
(
1
,
l
−
1
,
x
)
get(l,r,x)=get(1,r,x)-get(1,l-1,x)
get(l,r,x)=get(1,r,x)−get(1,l−1,x)。方便起见,我们令
g
e
t
(
i
,
x
)
=
g
e
t
(
1
,
i
,
x
)
get(i,x)=get(1,i,x)
get(i,x)=get(1,i,x),对原式做容斥可得:
所以可以把一个询问拆成
4
4
4个询问。那么对于某个询问的
(
l
,
r
)
(l,r)
(l,r),我们需要计算
g
e
t
(
1
,
l
,
x
)
∗
g
e
t
(
1
,
r
,
x
)
,
1
<
=
x
<
=
n
get(1,l,x)*get(1,r,x),1<=x<=n
get(1,l,x)∗get(1,r,x),1<=x<=n。那么需要两个计数数组,
n
u
m
l
[
i
]
numl[i]
numl[i]记录
[
1
,
l
]
[1,l]
[1,l]内
i
i
i的数量,
n
u
m
r
[
i
]
numr[i]
numr[i]记录
[
1
,
r
]
[1,r]
[1,r]内
i
i
i的数量。这里以
l
l
l递增为例说明如何计算
g
e
t
(
1
,
l
,
x
)
∗
g
e
t
(
1
,
r
,
x
)
,
1
<
=
x
<
=
n
get(1,l,x)*get(1,r,x),1<=x<=n
get(1,l,x)∗get(1,r,x),1<=x<=n,假设上一次询问的区间为
(
l
,
r
)
(l,r)
(l,r),结果为
r
e
s
res
res,这次询问的区间为
(
l
+
1
,
r
)
(l+1,r)
(l+1,r),显然要令
n
u
m
l
[
a
[
l
+
1
]
]
numl[a[l+1]]
numl[a[l+1]]自增
1
1
1,同时
r
e
s
+
=
n
u
m
r
[
a
[
l
+
1
]
]
res+=numr[a[l+1]]
res+=numr[a[l+1]]。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=5e4+5;
int n,m;
int a[maxn],pos[maxn];
ll res,ans[maxn],numl[maxn],numr[maxn];
struct node
{
int l,r,id,op;
node(){}
node(int l,int r,int i,int o):l(l),r(r),id(i),op(o){}
bool operator <(const node &a)const
{
if(pos[l]==pos[a.l])
return r<a.r;
return pos[l]<pos[a.l];
}
}q[maxn*4];
inline void addl(int val)
{
res+=numr[val];
++numl[val];
}
inline void subl(int val)
{
res-=numr[val];
--numl[val];
}
inline void addr(int val)
{
res+=numl[val];
++numr[val];
}
inline void subr(int val)
{
res-=numl[val];
--numr[val];
}
int main()
{
scanf("%d",&n);
int dis=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/dis+1;
}
scanf("%d",&m);
int l1,r1,l2,r2,len=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
q[len++]=node(r1,r2,i,1);
q[len++]=node(l1-1,r2,i,-1);
q[len++]=node(l2-1,r1,i,-1);
q[len++]=node(l1-1,l2-1,i,1);
}
sort(q,q+len);
int l=0,r=0;
for(int i=0;i<len;i++)
{
while(l<q[i].l)
addl(a[++l]);
while(l>q[i].l)
subl(a[l--]);
while(r<q[i].r)
addr(a[++r]);
while(r>q[i].r)
subr(a[r--]);
ans[q[i].id]+=res*q[i].op;
}
for(int i=0;i<m;i++)
printf("%lld\n",ans[i]);
return 0;
}