初尝莫队算法
来源:互联网 发布:优众网络 编辑:程序博客网 时间:2024/06/05 02:52
莫队算法是一种区间查询算法,它将查询的区间以左端为准分成了sqrt(n)份,然后每份中的区间以右端排序,之后维持一个查询的队列[l,r],记录答案。
注意:一定要先处理r2和r再处理l2和l!(不知道贡献了多少wa...)
例题:
hdoj :
http://acm.hdu.edu.cn/showproblem.php?pid=3874
题目大意:
n次询问,每次询问计算区间中不重复数字的代数和。
AC代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int M = 1000100;const int S = 200020;int necklace[M], hashtable[M];long long ans[S];int n;struct Query{ int l, r, dx; bool operator < (const Query &i) const { int l1 = l/sqrt(n);//将区间分成sqrt(n)份,并以右端排序 int l2 = i.l/sqrt(n); if(l1 == l2) return r < i.r; return l1 < l2; }}query[S];main(){ int T; scanf("%d", &T); while(T--) { memset(hashtable, 0, sizeof(hashtable)); scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &necklace[i]); int q; scanf("%d", &q); for(int i = 0; i < q; i++) { scanf("%d %d", &query[i].l, &query[i].r); query[i].dx = i; } sort(query, query + q); long long sum = 0; int l, r, l2 = 0, r2 = 0; for(int i = 0; i < q; i++) { l = query[i].l, r = query[i].r; if(r2 < r)//对可能出现的四种情况进行处理 一定要先右后左!! for(int j = r2 + 1; j <= r; j++) { if(hashtable[necklace[j]] == 0) { sum += necklace[j]; hashtable[necklace[j]]++; } else hashtable[necklace[j]]++; } if(r2 > r) for(int j = r2; j > r; j--) { if(hashtable[necklace[j]] == 1) { sum -= necklace[j]; hashtable[necklace[j]]--; } else if(hashtable[necklace[j]] > 1) hashtable[necklace[j]]--; } if(l2 < l) for(int j = l2; j < l; j++) { if(hashtable[necklace[j]] == 1) { sum -= necklace[j]; hashtable[necklace[j]]--; } else if(hashtable[necklace[j]] > 1) hashtable[necklace[j]]--; } if(l2 > l) for(int j = l2 - 1; j >= l; j--) { if(hashtable[necklace[j]] == 0) { sum += necklace[j]; hashtable[necklace[j]]++; } else hashtable[necklace[j]]++; } l2 = l, r2 = r; ans[query[i].dx] = sum; } for(int i = 0; i < q; i++) printf("%I64d\n", ans[i]); }}
0 0