P2709 小B的询问(莫队入门)

题目链接:https://www.luogu.org/problemnew/show/P2709

题目大意:中文题目

具体思路:莫队入门题,按照离线的方式打的,对每一个区间进行分块和编号,如果在同一个块里面就按照右端点从小到大排列,如果不在同一个块里面就按照块的下标开始排序,这里的块是按照数列分块里面的方法来进行的,查询每个区间的值就可以了。

对于l,r指针的移动,当l<q[i].l的时候,我们需要将l指针往右移动,所以假设t为当前的颜色,ans为未移动的时候的值,首先去除掉原来的值的影响,ans-=t*t,然后再加上新的值的影响,ans+=(t+1)*(t+1),因为我们是先进行加减操作,所以这种情况下ans=-(t-1)*(t-1)+t*t=2*t-1.其他情况同理。

AC代码:

 1 #include<iostream>
 2 #include<stack>
 3 #include<cstring>
 4 #include<iomanip>
 5 #include<stdio.h>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<vector>
 9 using namespace std;
10 # define ll long long
11 const int maxn = 2e5+100;
12 int a[maxn];
13 struct node{
14 int l,r,pos,id;
15 bool friend operator < (node t1,node t2){
16 if(t1.pos==t2.pos)return t1.r<t2.r;
17 return t1.pos<t2.pos;
18 }
19 }q[maxn];
20 int ans[maxn],vis[maxn];
21 int main(){
22 int n,m,k;
23 scanf("%d %d %d",&n,&m,&k);
24 int block=(int)sqrt(n);
25 for(int i=1;i<=n;i++){
26 scanf("%d",&a[i]);
27 }
28 for(int i=1;i<=m;i++){
29 scanf("%d %d",&q[i].l,&q[i].r);
30 q[i].pos=(q[i].l-1)/block+1;
31 q[i].id=i;
32 }
33 sort(q+1,q+m+1);
34 int tmp=0;
35 int l=1,r=0;
36 for(int i=1;i<=m;i++){
37 while(l<q[i].l)vis[a[l]]--,tmp-=(2*vis[a[l]]+1),l++;
38 while(l>q[i].l)l--,vis[a[l]]++,tmp+=2*vis[a[l]]-1;
39 while(r<q[i].r)r++,vis[a[r]]++,tmp+=2*vis[a[r]]-1;
40 while(r>q[i].r)vis[a[r]]--,tmp-=2*vis[a[r]]+1,r--;
41 ans[q[i].id]=tmp;
42 }
43 for(int i=1;i<=m;i++){
44 printf("%d
",ans[i]);
45 }
46 return 0;
47 }
原文地址:https://www.cnblogs.com/letlifestop/p/10487444.html