题目大意:一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。
思路:莫队走起。
CODE:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 50010 using namespace std; int belong[MAX],block_size; struct Ask{ int x,y,id; bool operator <(const Ask &a)const { if(belong[x] == belong[a.x]) return y <= a.y; return belong[x] < belong[a.x]; } void Read(int p) { scanf("%d%d",&x,&y); id = p; belong[p] = p / block_size; } }ask[MAX]; int cnt,asks; int src[MAX]; int v[MAX],now; int ans[MAX]; int main() { cin >> cnt >> asks; scanf("%*d"); block_size = sqrt(cnt); for(int i = 1; i <= cnt; ++i) scanf("%d",&src[i]); for(int i = 1; i <= asks; ++i) ask[i].Read(i); sort(ask + 1,ask + asks + 1); int l = 1,r = 0; for(int temp,i = 1; i <= asks; ++i) { while(r < ask[i].y) { temp = src[++r]; now -= v[temp] * v[temp]; ++v[temp]; now += v[temp] * v[temp]; } while(l > ask[i].x) { temp = src[--l]; now -= v[temp] * v[temp]; ++v[temp]; now += v[temp] * v[temp]; } while(l < ask[i].x) { temp = src[l++]; now -= v[temp] * v[temp]; --v[temp]; now += v[temp] * v[temp]; } while(r > ask[i].y) { temp = src[r--]; now -= v[temp] * v[temp]; --v[temp]; now += v[temp] * v[temp]; } ans[ask[i].id] = now; } for(int i = 1; i <= asks; ++i) printf("%d\n",ans[i]); return 0; }
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41549303