莫队。
统计ai[i]的出现次数,每一次先还原贡献,再加上或减去当前的贡献即可。
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<bitset> #include<map> //#include<regex> #include<cstdio> #include <iomanip> #pragma GCC optimize(2) #define up(i,a,b) for(int i=a;i<b;i++) #define dw(i,a,b) for(int i=a;i>b;i--) #define upd(i,a,b) for(int i=a;i<=b;i++) #define dwd(i,a,b) for(int i=a;i>=b;i--) //#define local typedef long long ll; typedef unsigned long long ull; const double esp = 1e-6; const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int inf = 1e9; using namespace std; ll read() { char ch = getchar(); ll x = 0, f = 1; while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } typedef pair<int, int> pir; #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lrt root<<1 #define rrt root<<1|1 const int N = 2e5 + 10; int ai[N], belong[N]; int n, t, block; ll ans = 0; int cnt[N * 10]; int L = 1, R; struct node { int l, r, id; bool operator<(const node temp)const { if (belong[l] == belong[temp.l]) { if (belong[l] & 1) { return r < temp.r; } else return r > temp.r; } else return l < temp.l; } }qr[N]; void add(int x) { ans -= 1ll * cnt[x] * x* cnt[x]; cnt[x]++; ans += 1ll * cnt[x] * x* cnt[x]; } void del(int x) { ans -= 1ll * cnt[x] * x* cnt[x]; cnt[x]--; ans += 1ll * cnt[x] * x* cnt[x]; } ll ans_mo[N]; void mo() { upd(i, 1, t) { while (L < qr[i].l)del(ai[L++]); while (L > qr[i].l)add(ai[--L]); while (R < qr[i].r)add(ai[++R]); while (R > qr[i].r)del(ai[R--]); ans_mo[qr[i].id] = ans; } upd(i, 1, t) { cout << ans_mo[i] << endl; } } int main() { cin >> n >> t; block = sqrt(n); upd(i, 1, n) { cin >> ai[i]; belong[i] = (i - 1) / block + 1; } upd(i, 1, t) { qr[i].id = i; qr[i].l = read(); qr[i].r = read(); } sort(qr + 1, qr + 1 + t); mo(); return 0; }
来源:https://www.cnblogs.com/LORDXX/p/12590958.html