题目描述
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
输入输出格式
输入格式:
第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
输出格式:
M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
输入输出样例
说明
对于全部的数据,1<=N、M、K<=50000
题解
- 题目大意:区间[L..R],求Sigma(c(i)^2),c[i]为i数字在区间出现的次数
- 这题显然就是小Z的袜子的弱化版,具体解法就可看链接里的博客
- 其实就是将小Z的袜子去掉分母
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define ll long long 7 #define N 50010 8 #define sqr(x) (x)*(x) 9 using namespace std; 10 struct edge { int l,r,d; ll a; }e[N]; 11 int n,m,num,bel[N],sum[N],a[N],k; 12 ll ans; 13 bool cmp(edge a,edge b) { return bel[a.l]==bel[b.l]?a.r<b.r:a.l<b.l; } 14 bool cmp1(edge a,edge b) { return a.d<b.d; } 15 void work(int x,int k) { ans-=sqr(sum[a[x]]),sum[a[x]]+=k,ans+=sqr(sum[a[x]]); } 16 int main() 17 { 18 scanf("%d%d%d",&n,&m,&k),num=sqrt(n); 19 for (int i=1;i<=n;i++) scanf("%d",&a[i]),bel[i]=i/num+1; 20 for (int i=1;i<=m;i++) scanf("%d%d",&e[i].l,&e[i].r),e[i].d=i; 21 sort(e+1,e+m+1,cmp); 22 int l=1,r=0; 23 for (int i=1;i<=m;i++) 24 { 25 while (l<e[i].l) work(l,-1),l++; 26 while (l>e[i].l) work(l-1,1),l--; 27 while (r<e[i].r) work(r+1,1),r++; 28 while (r>e[i].r) work(r,-1),r--; 29 e[i].a=ans; 30 } 31 sort(e+1,e+m+1,cmp1); 32 for (int i=1;i<=m;i++) printf("%lld ",e[i].a); 33 }