P2709 小B的询问
莫队
看一眼感觉是数据结构..
怎么看都是数据结构...
但是呢,数据结构要怎么搞我不会啊
换个思路,莫队
一下就会搞了..
稍微讲一下莫队:
莫队的思路很简单
首先考虑如果只是询问一个区间
从区间左边开始,累加答案,一直到右边
但如果已知一段区间的值,要搞另一段区间的值呢
首先把已知的区间扩大,更新值,直到把要询问的区间包住
那多出来的呢
从多出来的边界开始,往询问的边界靠近,走一步减一次
走到询问边界后就是答案了
但是如果是按输入顺序来处理..
明显会超时..
那就离线
先读入,排个序
让边界的移动次数减小
至于怎么排序
有一个套路
看程序就好
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=50007; struct data { int l,r,id,pos; bool operator < (const data &a) { if(pos!=a.pos) return pos<a.pos;//以pos为第一关键字排序 return r<a.r; } }d[N]; int a[N],cnt[N],n,m,k; long long ans[N],res; int main() { cin>>n>>m>>k; int t=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&d[i].l,&d[i].r); d[i].id=i; d[i].pos=(d[i].l-1)/t+1;//计算pos的套路 } sort(d+1,d+m+1); int l=1,r=0; for(int i=1;i<=m;i++) { while(l<d[i].l) res=res-cnt[a[l]]*2+1,cnt[a[l]]--,l++; while(r<d[i].r) r++,cnt[a[r]]++,res=res+cnt[a[r]]*2-1; while(l>d[i].l) l--,cnt[a[l]]++,res=res+cnt[a[l]]*2-1; while(r>d[i].r) res=res-cnt[a[r]]*2+1,cnt[a[r]]--,r--; //莫队的基本操作,在纸上画一画就懂了,至于为什么res可以这样跟新应该很显然吧(学过完全平方公式的人都懂...) ans[d[i].id]=res; } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; }