bzoj5016 [Snoi2017]一个简单的询问
分析
我们发现可以通过容斥得到Ans = sum(1,R1,1,R2) - sum(1,R1,1,L2-1) - sum(1,L1-1,1,R2) + sum(1,L1-1,L2-1)
于是我们可以吧一个询问分成4部分
然后进行莫队即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
int belong[400100],block,n,m,num1[400100],num2[400100],ans[400100],Ans,a[400100],cnt;
struct node {
int le,ri,id,wh;
};
node d[400100];
inline bool cmp(const node a,const node b){
if(belong[a.le]==belong[b.le])return a.ri<b.ri;
return a.le<b.le;
}
signed main(){
int i,j,k,L=1,R=0;
scanf("%lld",&n);
block=sqrt(n);
for(i=1;i<=n;i++)belong[i]=(i-1)/block+1;
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
scanf("%lld",&m);
for(i=1;i<=m;i++){
int x1,x2,y1,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
d[++cnt]=(node){y1,y2,i,1};
d[++cnt]=(node){x1-1,y2,i,-1};
d[++cnt]=(node){y1,x2-1,i,-1};
d[++cnt]=(node){x1-1,x2-1,i,1};
}
sort(d+1,d+cnt+1,cmp);
for(i=1;i<=cnt;i++){
while(L>d[i].le){
Ans-=num2[a[L]];
num1[a[L]]--;
L--;
}
while(L<d[i].le){
L++;
Ans+=num2[a[L]];
num1[a[L]]++;
}
while(R<d[i].ri){
R++;
Ans+=num1[a[R]];
num2[a[R]]++;
}
while(R>d[i].ri){
Ans-=num1[a[R]];
num2[a[R]]--;
R--;
}
ans[d[i].id]+=d[i].wh*Ans;
}
for(i=1;i<=m;i++)printf("%lld\n",ans[i]);
return 0;
}