~目录~
题目(4000ms)
描述
给你一个长度为
N
N
N的序列
a
i
a_i
ai,
1
≤
i
≤
N
1\leq i \leq N
1≤i≤N,和q组询问,每组询问读入
l
1
,
r
1
,
l
2
,
r
2
l_1,r_1,l_2,r_2
l1,r1,l2,r2,输出
∑
x
=
0
∞
g
e
t
(
l
1
,
r
1
,
x
)
∗
g
e
t
(
l
2
,
r
2
,
x
)
\sum_{x=0}^\infty get(l_1,r_1,x)*get(l_2,r_2,x)
x=0∑∞get(l1,r1,x)∗get(l2,r2,x)
g
e
t
(
l
,
r
,
x
)
get(l,r,x)
get(l,r,x)表示计算区间
[
l
,
r
]
[l,r]
[l,r]中,数
x
x
x出现了多少次
输入
第一行,一个数字
N
N
N,表示序列长度。
第二行,
N
N
N个数,表示
a
1
∼
a
n
a_1 \sim a_n
a1∼an 。
第三行,一个数字
Q
Q
Q,表示询问个数。
第
4
∼
Q
+
3
4 \sim Q+3
4∼Q+3行,每行四个数字
l
1
,
r
1
,
l
2
,
r
2
l_1, r_1,l_2,r_2
l1,r1,l2,r2,表示询问。
输出
对于每组询问,输出一行一个数字,表示答案。
范围
N
,
Q
≤
5
∗
1
0
4
,
1
≤
a
i
≤
N
,
1
≤
l
1
≤
r
1
≤
N
,
1
≤
l
2
≤
r
2
≤
N
N,Q\leq 5*10^4,1\leq a_i \leq N,1\leq l_1 \leq r_1 \leq N, 1\leq l_2 \leq r_2 \leq N
N,Q≤5∗104,1≤ai≤N,1≤l1≤r1≤N,1≤l2≤r2≤N
样例
样例输入
5
1 1 1 1 1
2
1 2 3 4
1 1 4 4
样例输出
4
1
思路
其实也是板题,既然它的询问有两个区间,那我们也搞两个
c
l
,
c
r
,
n
u
m
cl, cr, num
cl,cr,num
若
n
u
m
[
i
]
[
1
]
±
num[i][1]\pm
num[i][1]±,则
s
u
m
±
=
n
u
m
[
i
]
[
0
]
sum\pm=num[i][0]
sum±=num[i][0]
若
n
u
m
[
i
]
[
0
]
±
num[i][0]\pm
num[i][0]±,则
s
u
m
±
=
n
u
m
[
i
]
[
1
]
sum\pm=num[i][1]
sum±=num[i][1]
没了
Code
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define M 50005
#define LL long long
int n, m, bl;
int a[M], cl[2]={1,1}, cr[2];
LL num[M][2];
unsigned long long sum;
LL ans[M];
struct node{
int l1, r1, l2, r2, id;
bool operator < (const node &b)const{
if( (b.l1/bl) == (l1/bl) && r1 != b.r1 ){
if( (l1/bl)&1 )
return r1 > b.r1;
else return r1 < b.r1;
}
else if( (b.l2/bl) == (l2/bl) ){
if( (l2/bl)&1 )
return r2 > b.r2;
else return r2 < b.r2;
}
return l1 < b.l1;
}
}q[M];
inline void re(int x, int i){
num[a[x]][i]--;
sum -= num[a[x]][i^1];
}
inline void add(int x, int i){
num[a[x]][i]++;
sum += num[a[x]][i^1];
}
inline void mv(int l, int r, int i){
while( cl[i] < l )
re(cl[i]++, i);
while( cl[i] > l )
add(--cl[i], i);
while( cr[i] < r )
add(++cr[i], i);
while( cr[i] > r )
re(cr[i]--, i);
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; i ++){
scanf("%d%d%d%d", &q[i].l1, &q[i].r1, &q[i].l2, &q[i].r2);
q[i].id = i;
}
bl = n/sqrt(m*2/3*1.0);
sort(q+1, q+1+m);
for(int i = 1; i <= m; i ++){
mv(q[i].l1, q[i].r1, 0);
mv(q[i].l2, q[i].r2, 1);
ans[q[i].id] = sum;
}
for(int i = 1; i <= m; i ++)
printf("%lld\n", ans[i]);
}