【P2709】【BZOJ3781】 小B的询问 莫队算法
2018-03-26 18:16
531 查看
题目描述
小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<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #define ll long long const int MAXN=1e6; using namespace std; int n,m,block,k,answer,ans[MAXN],cnt[MAXN],val[MAXN]; struct Node { int l,r,pos; friend bool operator < (Node A,Node B)//排序 { if(A.l/block==B.l/block) return A.r<B.r; else return A.l/block<B.l/block; } }q[MAXN]; void Add(int x) { answer+=((cnt[val[x]]++))*2+1; } void Remove(int x) { answer-=((--cnt[val[x]]))*2+1; } void Moque() { int nowl=1,nowr=0; for(int i=1;i<=m;i++) { // cout<<"0"; while(nowl<q[i].l) Remove(nowl++); while(nowr>q[i].r) Remove(nowr--); while(nowl>q[i].l) Add(--nowl); while(nowr<q[i].r) Add(++nowr);//莫队板子 ans[q[i].pos]=answer; 4000 } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } int main() { // cout<<qsm(2,0); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].pos=i; } block=n/sqrt(m*2/3);//分块,听说这样可以快10% sort(q+1,q+m+1); // for(int i=1;i<=m;i++) cout<<q[i].l<<" "<<q[i].r<<endl; Moque(); return 0; }
相关文章推荐
- 【BZOJ】3781: 小B的询问(莫队算法)
- BZOJ 3781 小B的询问 序列莫队算法
- 【模板】BZOJ 3781: 小B的询问 莫队算法
- 【莫队算法】bzoj3781 小B的询问
- 【bzoj3781】小B的询问 莫队算法
- 【BZOJ3781】小B的询问【莫队算法】
- BZOJ - 3781 小B的询问 莫队算法
- 洛谷P2709 BZOJ 3781 小B的询问 (莫队)
- bzoj 3781 小B的询问(莫队算法)
- bzoj 3781: 小B的询问 莫队算法+分块
- BZOJ 3781: 小B的询问 莫队算法
- 【bzoj5016】[Snoi2017]一个简单的询问 莫队算法
- [BZOJ3781][小B的询问][莫队]
- BZOJ 3781: 小B的询问 [莫队]
- [bzoj3781]小B的询问【莫队】
- BZOJ3781【莫队算法】
- BZOJ_3781_小B的询问_莫队
- [BZOJ3781]小B的询问(莫队)
- bzoj3781 小B的询问【莫队】
- 3781: 小B的询问 莫队算法