Codefroce D. Powerful array[first knowledge block array]
Because it is the initial, we can only use the analysis of others first. I'm so embarrassed ...
Topic:
Given a sequence: A1, A2,......,an, defines the number of times the KS is present in the interval (l,r).
t queries, each query l,r, all a[i in the interval], Sigma (K^2*a[i])
Offline + chunking
Divides the number of n into sqrt (n) blocks.
Sort all queries, sort the criteria:
1. Q[i].left/block_size < Q[j].left/block_size (Block number prioritization)
2. If 1 is the same, then Q[i].right < Q[j].right (sorted by the right boundary of the query)
Problem solving:
The results of the current query are rolled out from the results of the previous query. (This looks at the part of the program in the query)
If a number has already appeared x times, then need to accumulate (2*x+1) *a[i], because (x+1) ^2*a[i] = (x^2 +2*x + 1) *a[i],x^2*a[i] is the result of X-times, (x+1) ^2 * A[i] is the result of x+1 times.
Time Complexity Analysis:
after finishing the sequence, for the next two queries, the difference between the left value is sqrt (n), then the number of <=SQRT (n) of each of the adjacent two queries is shifted by a total of t queries, and the complexity is O (t*sqrt (n)).
And for queries within the same block, the right endpoint is monotonically rising, with each block of operations, with a maximum of O (n) times, the total number of blocks sqrt (n), and the complexity of O (sqrt (n) *n).
The complexity of right and left is independent, so the total time complexity is O (t*sqrt (n) + n*sqrt (n)).
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include < Cmath>using namespace Std;typedef long long ll;const int V = 200000 + 10;const int maxn = 1000000 + 10;struct node{I NT L,r,id;} Query[v];int N,T,NUM[V],L,R,SUM[MAXN]; LL Ans[maxn],now;bool CMP (node A,node b) {int m = sqrt (1.0*n); The best theoretical value if (a.l/m! = b.l/m) {return A.L < B.L; } return A.R < B.R;} void Modify (int l,int R) {while (L < L) {///left band does not contain sum[num[l]]--; Now-= num[l] * (Sum[num[l]] << 1 | 1); l++; } while (R > R) {//Right interval does not contain sum[num[r]]--; Now-= num[r] * (Sum[num[r]] << 1 | 1); r--; } while (L > L) {//The left interval of the previous interval is contained in the current interval l--; Now + = num[l] * (Sum[num[l]] << 1 | 1); sum[num[l]]++; } while (R < R) {//The right interval of the previous interval is contained in the current interval r++; Now + = num[r] * (Sum[num[r]] << 1 | 1); sum[num[r]]++; }}int Main () {while (~sCANF ("%d%d", &n,&t)) {for (int i = 1;i <= n;++i) {scanf ("%d", &num[i]); } for (int i = 1;i <= t;++i) {scanf ("%d%d", &QUERY[I].L,&QUERY[I].R); Query[i].id = i; } sort (Query+1,query + t + 1,cmp); now = L = R = 0; memset (sum,0,sizeof (sum)); for (int i = 1;i <= t;++i) {modify (QUERY[I].L,QUERY[I].R); Ans[query[i].id] = now; } for (int i = 1;i <= t;++i) {printf ("%i64d\n", Ans[i]); }} return 0;}
Codefroce D. Powerful array[first knowledge block array]