1. 程式人生 > >(莫隊算法)兩題莫隊算法統計數量的入門題

(莫隊算法)兩題莫隊算法統計數量的入門題

做了 ostream origin scan cmp opened ems view isp

因為這兩題差不多,而且比較簡單,就放一起,做了這題,這種題目就是巨水的題了。隨便寫都行。

CodeForces - 86D Powerful array

題意:

多次查詢數列中從L到R每個數字出現次數的平方乘這個數字的和。

代碼:

技術分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cmath>
 5 #include <map>
 6 #include <vector>
 7
#include <algorithm> 8 9 using namespace std; 10 11 const int maxn = 200010; 12 const int bk = 350; 13 int n, q; 14 int a[maxn]; 15 struct Query { 16 int l, r, index; 17 }; 18 int cnt[maxn * 5]; 19 20 Query query[maxn]; 21 22 bool cmp(Query a, Query b) { 23 if(a.l / bk == b.l / bk)return
a.r < b.r; 24 else return a.l / bk < b.l / bk; 25 } 26 27 long long ans[maxn]; 28 long long res = 0; 29 30 void add(int x) { 31 res += x * (2 * cnt[x] + 1); 32 cnt[x]++; 33 } 34 35 void del(int x) { 36 cnt[x]--; 37 res -= x * (2 * cnt[x] + 1); 38 } 39 40 int
main() { 41 scanf("%d", &n); 42 scanf("%d", &q); 43 for(int i = 1; i <= n; i++) { 44 scanf("%d", &a[i]); 45 } 46 for(int i = 0; i < q; i++) { 47 scanf("%d%d", &query[i].l, &query[i].r); 48 query[i].index = i; 49 } 50 sort(query, query + q, cmp); 51 int left = 1, right = 0; 52 for(int i = 0; i < q; i++) { 53 if(right < query[i].r) { 54 for(int j = right + 1; j <= query[i].r; j++) { 55 add(a[j]); 56 } 57 } else { 58 for(int j = right; j > query[i].r; j--) { 59 del(a[j]); 60 } 61 } 62 right = query[i].r; 63 if(left < query[i].l) { 64 for(int j = left; j < query[i].l; j++) { 65 del(a[j]); 66 } 67 68 } else { 69 for(int j = left - 1; j >= query[i].l; j--) { 70 add(a[j]); 71 } 72 } 73 left = query[i].l; 74 ans[query[i].index] = res; 75 } 76 for(int i = 0; i < q; i++) { 77 printf("%lld\n", ans[i]); 78 79 } 80 81 return 0; 82 }
View Code

NBUT - 1457 Sona

題意:

多次查詢數列中L到R買個數字出現次數的立方和。

特別註意:

註意復雜度,因為數值較大,如果用map加個log的復雜度,可能會超時,而這個OJ沒有開C++11,無法使用unordered_map,所以一定要先離散化。

畢竟因為答案只跟次數有關跟值無關,所以無影響。

代碼:

技術分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <cmath>
  5 #include <map>
  6 #include <vector>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 
 11 inline bool scan_d(int &num) {
 12     char in;
 13     bool IsN = false;
 14     in = getchar();
 15     if(in == EOF) return false;
 16     while(in != - && (in < 0 || in > 9)) in = getchar();
 17     if(in == -) {
 18         IsN = true;
 19         num = 0;
 20     } else num = in - 0;
 21     while(in = getchar(), in >= 0 && in <= 9) {
 22         num *= 10, num += in - 0;
 23     }
 24     if(IsN) num = -num;
 25     return true;
 26 }
 27 
 28 
 29 const int maxn = 100010;
 30 const int bk = 400;
 31 int n, q;
 32 int a[maxn];
 33 int b[maxn];
 34 struct Query {
 35     int l, r, index;
 36 };
 37 int cnt[maxn];
 38 
 39 Query query[maxn];
 40 
 41 bool cmp(Query a, Query b) {
 42     if(a.l / bk == b.l / bk)return a.r < b.r;
 43     else return a.l / bk < b.l / bk;
 44 }
 45 
 46 long long ans[maxn];
 47 long long res = 0;
 48 
 49 void add(int x) {
 50     res += 3 * cnt[x] * cnt[x] + 3 * cnt[x] + 1;
 51     cnt[x]++;
 52 }
 53 
 54 void del(int x) {
 55     cnt[x]--;
 56     res -= 3 * cnt[x] * cnt[x] + 3 * cnt[x] + 1;
 57 }
 58 
 59 
 60 void init() {
 61     sort(b + 1, b + n + 1);
 62     int pp = unique(b + 1, b + n + 1) - b;
 63     for(int i = 1; i <= n; i++) {
 64         a[i] = lower_bound(b + 1, b + pp + 1, a[i]) - b;
 65     }
 66 }
 67 
 68 int main() {
 69     while(scan_d(n)) {
 70         memset(cnt, 0, sizeof cnt);
 71         res = 0;
 72         for(int i = 1; i <= n; i++) {
 73             scan_d(a[i]);
 74             b[i] = a[i];
 75         }
 76         init();
 77         scan_d(q);
 78         for(int i = 0; i < q; i++) {
 79             scan_d(query[i].l);
 80             scan_d(query[i].r);
 81             query[i].index = i;
 82         }
 83         sort(query, query + q, cmp);
 84         int left = 1, right = 0;
 85         for(int i = 0; i < q; i++) {
 86             if(right < query[i].r) {
 87                 for(int j = right + 1; j <= query[i].r; j++) {
 88                     add(a[j]);
 89                 }
 90             } else {
 91                 for(int j = right; j > query[i].r; j--) {
 92                     del(a[j]);
 93                 }
 94             }
 95             right = query[i].r;
 96             if(left < query[i].l) {
 97                 for(int j = left; j < query[i].l; j++) {
 98                     del(a[j]);
 99                 }
100 
101             } else {
102                 for(int j = left - 1; j >= query[i].l; j--) {
103                     add(a[j]);
104                 }
105             }
106             left = query[i].l;
107             ans[query[i].index] = res;
108         }
109         for(int i = 0; i < q; i++) {
110             printf("%I64d\n", ans[i]);
111         }
112     }
113 
114     return 0;
115 }
View Code

(莫隊算法)兩題莫隊算法統計數量的入門題