P5268 [SNOI2017]一个简单的询问

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;
}
posted @ 2021-04-21 19:37  __Anchor  阅读(56)  评论(0编辑  收藏  举报