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

Solution

懒得写一遍公式了直接放大爷的题解吧……

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define N (500009)
 7 #define LL long long
 8 #define MOD (1000000007)
 9 using namespace std;
10 
11 struct Node{int l,r,id,opt; LL ans;}Q[N*4];
12 int n,a[N],m,c1[N],c2[N],ID[N],q_num;
13 LL ans,S[N];
14 
15 inline int read()
16 {
17     int x=0,w=1; char c=getchar();
18     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
19     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
20     return x*w;
21 }
22 
23 void Ins(int opt,int p)
24 {
25     ans-=1ll*c1[a[p]]*c2[a[p]];
26     if (opt==1) ++c1[a[p]];
27     else ++c2[a[p]];
28     ans+=1ll*c1[a[p]]*c2[a[p]];
29 }
30 
31 void Del(int opt,int p)
32 {
33     ans-=1ll*c1[a[p]]*c2[a[p]];
34     if (opt==1) --c1[a[p]];
35     else --c2[a[p]];
36     ans+=1ll*c1[a[p]]*c2[a[p]];
37 }
38 
39 bool cmp(Node a,Node b)
40 {
41     if (ID[a.l]==ID[b.l]) return a.r<b.r;
42     return ID[a.l]<ID[b.l];
43 }
44 
45 int main()
46 {
47     n=read(); int unit1=sqrt(n);
48     for (int i=1; i<=n; ++i) a[i]=read(),ID[i]=i/unit1;
49     m=read();
50     for (int i=1; i<=m; ++i)
51     {
52         int l1=read(),r1=read(),l2=read(),r2=read();
53         Q[++q_num]=(Node){r1,r2,i,1};
54         Q[++q_num]=(Node){l1-1,r2,i,-1};
55         Q[++q_num]=(Node){r1,l2-1,i,-1};
56         Q[++q_num]=(Node){l1-1,l2-1,i,1};
57     }
58     sort(Q+1,Q+4*m+1,cmp);
59     int l=0,r=0;
60     for (int i=1; i<=4*m; ++i)
61     {
62         while (l<Q[i].l) Ins(1,++l);
63         while (l>Q[i].l) Del(1,l--);
64         while (r<Q[i].r) Ins(2,++r);
65         while (r>Q[i].r) Del(2,r--);
66         Q[i].ans=ans;
67     }
68     for (int i=1; i<=4*m; ++i)
69         S[Q[i].id]+=Q[i].ans*Q[i].opt;
70     for (int i=1; i<=m; ++i) printf("%lld\n",S[i]);
71 }
posted @ 2019-02-16 21:59  Refun  阅读(217)  评论(0编辑  收藏  举报