算法学习:莫队
【luogu P3901】数列找不同
【题意】给一整数序列,Q个询问,询问区间内数字是否互不相同
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 const int MAXN = 100010; 7 ll a[MAXN],cnt[MAXN],ans[MAXN],c; 8 int siz; 9 struct node 10 { 11 int l, r, id; 12 bool operator<(node a) 13 { 14 if (((l - 1) / siz) == ((a.l - 1) / siz)) 15 return r < a.r; 16 return l / siz < a.l / siz; 17 } 18 }mo[MAXN]; 19 void add(int pos) 20 { 21 22 cnt[pos]++; 23 if(cnt[pos]==1) 24 c++; 25 } 26 void del(int pos) 27 { 28 cnt[pos]--; 29 if(cnt[pos]==0) 30 c--; 31 } 32 int main() 33 { 34 int n, m, k; 35 scanf("%d%d", &n, &m); 36 siz = (int)sqrt(n); 37 for (int i = 1; i <= n; i++) 38 { 39 scanf("%d", &a[i]); 40 } 41 for (int i = 1; i <= m; i++) 42 { 43 scanf("%d%d", &mo[i].l, &mo[i].r); 44 mo[i].id = i; 45 } 46 sort(mo + 1, mo + 1 + m); 47 int ansl=1, ansr=0; 48 for (int i = 1; i <= m; i++) 49 { 50 int l = mo[i].l, r = mo[i].r; 51 while (ansl > l) ansl--, add(a[ansl]); 52 while (ansr < r) ansr++, add(a[ansr]); 53 while (ansl < l) del(a[ansl]), ansl++; 54 while (ansr > r) del(a[ansr]), ansr--; 55 ans[mo[i].id] = c==r-l+1; 56 } 57 58 for (int i = 1; i <= m; i++) 59 printf("%s\n", ans[i]?"Yes":"No"); 60 61 62 return 0; 63 }
【luogu 2709】小B的询问
【题意】给一整数序列,值域为1~k,m个询问,每次询问区间内的每个数字出现次数的平方和
#include<cstdio> #include<cmath> #include<algorithm> #define ll long long using namespace std; const int MAXN = 50010; ll a[MAXN],cnt[MAXN],ans[MAXN],c; int siz; struct node { int l, r, id; bool operator<(node a) { if (((l - 1) / siz) == ((a.l - 1) / siz)) return r < a.r; return l / siz < a.l / siz; } }mo[MAXN]; void add(int pos) { c += 2 * cnt[pos] + 1; cnt[pos]++; } void del(int pos) { c -= 2 * cnt[pos] - 1; cnt[pos]--; } int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); siz = (int)sqrt(n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for (int i = 1; i <= m; i++) { scanf("%d%d", &mo[i].l, &mo[i].r); mo[i].id = i; } sort(mo + 1, mo + 1 + m); int ansl=1, ansr=0; for (int i = 1; i <= m; i++) { int l = mo[i].l, r = mo[i].r; while (ansl > l) ansl--, add(a[ansl]); while (ansr < r) ansr++, add(a[ansr]); while (ansl < l) del(a[ansl]), ansl++; while (ansr > r) del(a[ansr]), ansr--; ans[mo[i].id] = c; } for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return 0; }