标签:包括 oid span .com 排序 意思 turn 传送门 ble
题意:n个整数\(a_1,a_2...a_n\),q个询问,每个询问包括四个整数\(l_1,r_1,l_2,r_2\),求满足下列三个条件的整数对\((i,j)\)de个数:
\(a_i=a_j\)
\(l_1<=i<=r_1\)
\(l_2<=j<=r_2\)
这道题其实就是道裸莫队,但前提是理解了这道题的意思.不妨看做有两个区间\([l_1,r_1],[l_2,r_2]\),我们要维护的就是这两个区间内每个数的个数,则根据题意,两个区间内相等的数的个数的乘积之和就是\(ans\).
于是我们按照普通莫队的做法,把每个询问以\(l_1,r_1\)为关键字排序,然后暴力维护\(l_2,r_2\)即可.
int n,m,t,l1=1,r1,l2=1,r2;
int a[50005],place[50005];
int tot1[50005],tot2[50005];
long long Ans,ans[50005];
struct A{
int l1,r1,l2,r2,id;
}query[50001];
bool cmp(A x,A y){
return place[x.l1]==place[y.l1]?x.r1<y.r1:x.l1<y.l1;
}
void change1(int x,int y){
Ans-=(long long)tot1[x]*tot2[x];
tot1[x]+=y;
Ans+=(long long)tot1[x]*tot2[x];
}
void change2(int x,int y){
Ans-=(long long)tot1[x]*tot2[x];
tot2[x]+=y;
Ans+=(long long)tot1[x]*tot2[x];
}
int main(){
n=read();t=sqrt(n);
for(int i=1;i<=n;i++)
a[i]=read(),place[i]=i/t+1;
m=read();
for(int i=1;i<=m;i++){
query[i].l1=read();query[i].r1=read();
query[i].l2=read();query[i].r2=read();
query[i].id=i;
}
sort(query+1,query+m+1,cmp);
for(int i=1;i<=m;i++){
while(l1<query[i].l1)change1(a[l1],-1),l1++;
while(query[i].l1<l1)change1(a[l1-1],1),l1--;
while(r1<query[i].r1)change1(a[r1+1],1),r1++;
while(query[i].r1<r1)change1(a[r1],-1),r1--;
while(l2<query[i].l2)change2(a[l2],-1),l2++;
while(query[i].l2<l2)change2(a[l2-1],1),l2--;
while(r2<query[i].r2)change2(a[r2+1],1),r2++;
while(query[i].r2<r2)change2(a[r2],-1),r2--;
ans[query[i].id]=Ans;
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}
标签:包括 oid span .com 排序 意思 turn 传送门 ble
原文地址:https://www.cnblogs.com/PPXppx/p/10327177.html