莫队算法就是优化的暴力算法。莫队算法是要把询问先按左端点属于的块排序,再按右端点排序。只是预先知道了所有的询问。可以合理的组织计算每个询问的顺序以此来降低复杂度。
典型的莫队算法题
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <stack> 11 #include <queue> 12 #include <sstream> 13 #include <iomanip> 14 using namespace std; 15 typedef long long LL; 16 const int INF=0x4fffffff; 17 const int EXP=1e-5; 18 const int MS=200005; 19 20 int a[MS]; 21 int cnt[5*MS]; 22 LL ans[MS]; 23 24 struct node 25 { 26 int l,r; 27 int no,qid; 28 bool operator <(const node &a)const 29 { 30 return no<a.no||(no==a.no&&r<a.r); 31 } 32 }nodes[MS]; 33 34 35 int n,SIZE; 36 LL res; 37 int L,R; 38 LL query(int x,int y,int flag) 39 { 40 if(flag) 41 { 42 for(int i=x;i<L;i++) 43 { 44 res+=(cnt[a[i]]<<1|1)*a[i]; 45 cnt[a[i]]++; 46 } 47 for(int i=L;i<x;i++) 48 { 49 cnt[a[i]]--; 50 res-=(cnt[a[i]]<<1|1)*a[i]; 51 } 52 for(int i=R+1;i<=y;i++) 53 { 54 res+=(cnt[a[i]]<<1|1)*a[i]; 55 cnt[a[i]]++; 56 } 57 for(int i=y+1;i<=R;i++) 58 { 59 cnt[a[i]]--; 60 res-=(cnt[a[i]]<<1|1)*a[i]; 61 } 62 } 63 else 64 { 65 for(int i=x;i<=y;i++) 66 { 67 res+=(cnt[a[i]]<<1|1)*a[i]; 68 cnt[a[i]]++; 69 } 70 } 71 L=x;R=y; 72 return res; 73 } 74 75 int main() 76 { 77 int Q; 78 scanf("%d%d",&n,&Q); 79 for(int i=1;i<=n;i++) 80 { 81 scanf("%d",&a[i]); // 注意%d的速度远大于%I64d的速度 82 // 在大量数据输入时,能用%d就不要用%I64d,但千万要注意数据溢出 83 } 84 SIZE=sqrt(n+0.5); 85 for(int i=0;i<Q;i++) 86 { 87 scanf("%d%d",&nodes[i].l,&nodes[i].r); 88 nodes[i].no=nodes[i].l/SIZE; 89 nodes[i].qid=i; 90 } 91 sort(nodes,nodes+Q); 92 memset(cnt,0,sizeof(cnt)); 93 res=0; 94 for(int i=0;i<Q;i++) 95 ans[nodes[i].qid]=query(nodes[i].l,nodes[i].r,i); 96 for(int i=0;i<Q;i++) 97 printf("%I64d ",ans[i]); 98 return 0; 99 }