1. 程式人生 > >BZOJ5016:[SNOI2017]一個簡單的詢問(莫隊)

BZOJ5016:[SNOI2017]一個簡單的詢問(莫隊)

gen mat unit src long cmp nod \n 公式

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 }

BZOJ5016:[SNOI2017]一個簡單的詢問(莫隊)