因为这两题差不多,而且比较简单,就放一起,做了这题,这种题目就是巨水的题了。随便写都行。
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 }
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 }