洛谷 P2709 小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<=N、M、K<=50000
题解:
这题就是在莫队入门题上做了一点修改。
前面的分块、排序、指针 l,r 的移动没变,变的是更新状态这一部分:
1 void revise(int x,int w) 2 { 3 if (w>0) sum+=2*num[a[x]]+1; 4 if (w<0) sum-=2*num[a[x]]-1; 5 num[a[x]]+=w; 6 }
设 i 在此段中的数量为 x ,若是新增一个 i ,则根据公式可推出:ans+=(x+1)^2-x^2 ==> 2x+1
若是减少一个 i ,根据公式可推出:ans-=x^2-(x-1)^2 ==> 2x-1
还要注意一个非常重要的细节(所有的莫队题目都要注意!!!我在这个地方卡了超长时间,终于调出来了), 一开始的指针 l 和 r 初始化要注意, l=1, r=0
这个要切记,不然就会WA(因为 l=0 的话就会把下标为 -1 的这个点算上去)。
废话不多说,上代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=50005; 5 ll n,m,k,a[N],sum,num[N],block,belong[N],ans[N]; 6 struct node{ 7 int l,r,id; 8 }q[N]; 9 inline ll read() 10 { 11 ll x=0,f=1; char ch=getchar(); 12 while (!isdigit(ch)) 13 f=(ch=='-')?-f:f,ch=getchar(); 14 while (isdigit(ch)) 15 x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 16 return x*f; 17 } 18 bool cmp(node a,node b) 19 { 20 return belong[a.l]==belong[b.l]?a.r<b.r:belong[a.l]<belong[b.l]; 21 } 22 inline ll sqr(int x) 23 { 24 return x*x; 25 } 26 void revise(int x,int w) 27 { 28 ///* 29 if (w>0) sum+=2*num[a[x]]+1; 30 if (w<0) sum-=2*num[a[x]]-1; 31 num[a[x]]+=w; 32 //*/ 33 /* 34 num[a[x]]+=w; 35 if (w>0) sum+=2*num[a[x]]-1; 36 if (w<0) sum-=2*num[a[x]]+1; 37 */ 38 /*if (w>0) sum+=num[a[x]]<<1|1,num[a[x]]+=w; 39 if (w<0) num[a[x]]+=w,sum-=num[a[x]]<<1|1; 40 //num[a[x]]+=w; 41 */ 42 43 } 44 int main() 45 { 46 n=read(),m=read(),k=read(); 47 block=sqrt(n); 48 for (int i=1; i<=n; i++) 49 { 50 a[i]=read(); belong[i]=i/block+1; 51 } 52 for (int i=1; i<=m; i++) 53 { 54 q[i].l=read(),q[i].r=read(),q[i].id=i; 55 } 56 sort(q+1,q+1+m,cmp); 57 int zl=1,zr=0; sum=0; 58 memset(num,0,sizeof(num)); 59 for (int i=1; i<=m; i++) 60 { 61 while (zl<q[i].l) revise(zl,-1),zl++; 62 while (zl>q[i].l) revise(zl-1,1),zl--; 63 while (zr<q[i].r) revise(zr+1,1),zr++; 64 while (zr>q[i].r) revise(zr,-1),zr--; 65 ans[q[i].id]=sum; 66 } 67 for (int i=1; i<=m; i++) 68 { 69 printf("%lld ",ans[i]); 70 } 71 return 0; 72 }
加油加油加油!!! fighting fighting fighting !!!