bzoj5016 [Snoi2017]一个简单的询问

Description

给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 
get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。

Input

第一行,一个数字N,表示序列长度。
第二行,N个数字,表示a1~aN
第三行,一个数字Q,表示询问个数。
第4~Q+3行,每行四个数字l1,r1,l2,r2,表示询问。
N,Q≤50000
N1≤ai≤N
1≤l1≤r1≤N
1≤l2≤r2≤N
注意:答案有可能超过int的最大值

Output

对于每组询问,输出一行一个数字,表示答案 

Sample Input

5
1 1 1 1 1
2
1 2 3 4
1 1 4 4

Sample Output

4
1

正解:莫队算法。

把每个询问看成一个矩形,拆成$4$个二维前缀和类型的子矩形。

然后直接用莫队就可以得出答案了,注意这个莫队的姿势和普通莫队有点不一样。。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define N (200010)
 6 
 7 using namespace std;
 8 
 9 struct data{ int i,l,r,v; }q[N];
10 
11 int a[N],bl[N],cntl[N],cntr[N],Q,n,cnt,block;
12 ll ans[N];
13 
14 il int gi(){
15   RG int x=0,q=1; RG char ch=getchar();
16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
17   if (ch=='-') q=-1,ch=getchar();
18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
19   return q*x;
20 }
21 
22 il int cmp(const data &a,const data &b){
23   if (bl[a.l]==bl[b.l]) return a.r<b.r; return bl[a.l]<bl[b.l];
24 }
25 
26 int main(){
27 #ifndef ONLINE_JUDGE
28   freopen("query.in","r",stdin);
29   freopen("query.out","w",stdout);
30 #endif
31   n=gi(),block=sqrt(n);
32   for (RG int i=1;i<=n;++i) a[i]=gi(),bl[i]=(i-1)/block+1; Q=gi();
33   for (RG int i=1,l1,r1,l2,r2;i<=Q;++i){
34     l1=gi(),r1=gi(),l2=gi(),r2=gi();
35     q[++cnt]=(data){i,r1,r2,1};
36     q[++cnt]=(data){i,l1-1,r2,-1};
37     q[++cnt]=(data){i,r1,l2-1,-1};
38     q[++cnt]=(data){i,l1-1,l2-1,1};
39   }
40   for (RG int i=1;i<=cnt;++i) if (q[i].l>q[i].r) swap(q[i].l,q[i].r);
41   sort(q+1,q+cnt+1,cmp); RG int L=0,R=0; RG ll Ans=0;
42   for (RG int i=1;i<=cnt;++i){
43     if (!q[i].l || !q[i].r) continue;
44     while (L>q[i].l) Ans-=cntr[a[L]],--cntl[a[L--]];
45     while (R<q[i].r) ++cntr[a[++R]],Ans+=cntl[a[R]];
46     while (L<q[i].l) ++cntl[a[++L]],Ans+=cntr[a[L]];
47     while (R>q[i].r) Ans-=cntl[a[R]],--cntr[a[R--]];
48     ans[q[i].i]+=1LL*q[i].v*Ans;
49   }
50   for (RG int i=1;i<=Q;++i) printf("%lld
",ans[i]); return 0;
51 }
原文地址:https://www.cnblogs.com/wfj2048/p/7499315.html