P5268 [SNOI2017]一个简单的询问
莫队+差分。
首先这里是两个区间,显然不好直接做,于是可以考虑差分,我们维护前缀区间,把柿子改写成四个答案组合起来。
这样改写出来的四个小答案都可以使用莫队来求,然后拼起来就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
const int N=5e5+5;
int n,m,a[N];
int bl[N],cnt[N],d[N],siz;
ll Ans[N],now,Num[N],tl[N],tr[N];
struct Query{
int l,r,id,tag;
inline bool operator<(const Query&d)const{return bl[l]!=bl[d.l]?l<d.l:(bl[l]&1?r<d.r:r>d.r);}
}Q[N];
int main(){
read(n);
for(int i=1;i<=n;i++) read(a[i]);
read(m);int top=0;
for(int i=1;i<=m;i++){
int l1,r1,l2,r2;
read(l1),read(r1),read(l2),read(r2);
Q[++top]=Query{r1,r2,i,1};
Q[++top]=Query{l2-1,r1,i,-1};
Q[++top]=Query{l1-1,r2,i,-1};
Q[++top]=Query{l1-1,l2-1,i,1};
}
const int t=sqrt(top);
for(int i=1;i<=n;i++) bl[i]=(i-1)/t+1;
sort(Q+1,Q+top+1);
int l=0,r=0;
for(int i=1;i<=top;i++){
if(Q[i].l<1||Q[i].r<1)continue;
while(l<Q[i].l) now+=tr[a[++l]],++tl[a[l]];
while(l>Q[i].l) now-=tr[a[l]],--tl[a[l--]];
while(r<Q[i].r) now+=tl[a[++r]],++tr[a[r]];
while(r>Q[i].r) now-=tl[a[r]],--tr[a[r--]];
Ans[Q[i].id]+=now*Q[i].tag;
}
for(int i=1;i<=m;i++) write(Ans[i]),putchar('\n');
return 0;
}