小B的询问
Posted hrj1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小B的询问相关的知识,希望对你有一定的参考价值。
题目描述
小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
6 4 3 1 3 2 1 1 3 1 4 2 6 3 5 5 6
输出 #1
6 9 5 2
说明/提示
对于全部的数据,1<=N、M、K<=50000
很显然我们移动的越少
跑得就越快是吧?
所以我们把询问抽象成点
就是要求曼哈顿距离的最小生成树。
#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdio> #define MAXN 50001 using namespace std; int n,m,k,qwq,bz; int a[MAXN],cnt[MAXN],ans[MAXN]; struct node int l,r,num; ask[MAXN]; inline int read() int x=0;bool f=0;char c=getchar(); while(c<‘0‘||c>‘9‘)if(c==‘-‘)f=!f;c=getchar(); while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘;c=getchar(); return f?-x:x; inline bool cmp(node x,node y) return (x.num/bz==y.num/bz)?x.r<y.r:x.l<y.l; inline void remove(int pos) qwq-=cnt[a[pos]]*cnt[a[pos]],--cnt[a[pos]]; qwq+=cnt[a[pos]]*cnt[a[pos]]; inline void add(int pos) qwq-=cnt[a[pos]]*cnt[a[pos]],++cnt[a[pos]]; qwq+=cnt[a[pos]]*cnt[a[pos]]; int main() n=read(),m=read(),k=read(); bz=sqrt(n); for(register int i=1;i<=n;++i) a[i]=read(); for(register int i=1;i<=m;++i) ask[i].num=i; ask[i].l=read(),ask[i].r=read(); sort(ask+1,ask+m+1,cmp); int nl=1,nr=0; for(register int i=1;i<=m;++i) int L=ask[i].l,R=ask[i].r; while(nl<L) remove(nl++); while(nl>L) add(--nl); while(nr<R) add(++nr); while(nr>R) remove(nr--); ans[ask[i].num]=qwq; for(register int i=1;i<=m;++i) printf("%d\n",ans[i]); return 0;
以上是关于小B的询问的主要内容,如果未能解决你的问题,请参考以下文章