题解 P1494 【[国家集训队]小Z的袜子】(基础莫队总结)
题目link
在某题解的基础上解释一下
fk和FK数组是分块优化
看完这篇咕咕日报 您就可以对基础莫队比较了解了
代码很简单,主要是gcd居然有函数(手动致远星++)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,col[50010],ans,L=1,R,s[50010],FK[50010];
struct node
{
ll l;//左
ll r;//右
ll place;//原位置
ll numerator;//分子
ll denominator;//分母
}Q[50010];//question
ll update(ll x,ll fh)
{
ans-=s[col[x]]*s[col[x]];
s[col[x]]+=fh;
ans+=s[col[x]]*s[col[x]];
}
int cmp(node a,node b)
{
if(FK[a.l]!=FK[b.l])
return a.l<b.l;
return a.r<b.r;
}
int Cmp(node a,node b)
{
return a.place<b.place;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>col[i];
}
int fk=sqrt(n);
for(int i=1;i<=m;i++)
{
cin>>Q[i].l>>Q[i].r;
Q[i].place=i;
}
for(int i=1;i<=n;i++)
{
FK[i]=(i-1)/fk+1;
}
sort(Q+1,Q+m+1,cmp);
for(int i=1;i<=m;i++)
{
for(;R<Q[i].r;R++)
{
update(R+1,1);
}
for(;R>Q[i].r;R--)
{
update(R,-1);
}
for(;L<Q[i].l;L++)
{
update(L,-1);
}
for(;L>Q[i].l;L--)
{
update(L-1,1);
}
if(Q[i].l==Q[i].r)
{
Q[i].numerator=0;
Q[i].denominator=1;
continue;
}
Q[i].numerator=ans-(Q[i].r-Q[i].l+1);
Q[i].denominator=(Q[i].r-Q[i].l+1)*(Q[i].r-Q[i].l);
ll tmp=__gcd(Q[i].numerator,Q[i].denominator);
Q[i].numerator/=tmp;
Q[i].denominator/=tmp;
}
sort(Q+1,Q+m+1,Cmp);
for(int i=1;i<=m;i++)
{
cout<<Q[i].numerator<<"/"<<Q[i].denominator<<endl;
}
}
然后是可爱毒瘤的回滚莫队
更好的食用体验请点这里
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,col[5000010],ans,L=1,R,s[5000010],FK[5000010],GG;
int fk;
struct node
{
ll l;//左
ll r;//右
ll place;//原位置
ll ANS;
}Q[5000010];//question
int cmp(node a,node b)
{
if(FK[a.l]!=FK[b.l])
return a.l<b.l;
return a.r<b.r;
}
int Cmp(node a,node b)
{
return a.place<b.place;
}
int BaoLi(int x,int y)
{
int res=-1;
for(int i=x;i<=y;i++)
{
if(col[i]>res)
{
res=col[i];
}
}
return res;
}
int md(int x,int y)
{
L=min(x*fk,n)+1;
R=L-1;
ans=0;
int RET=y;
for(int i=y;FK[Q[i].l]==x;i++)
{
if(FK[Q[i].l]==FK[Q[i].r])
{
Q[i].ANS=BaoLi(Q[i].l,Q[i].r);
}
for(;R<=Q[i].r;)
{
ans=max(ans,col[R]);
R++;
}
int fy=ans;
for(;L>=Q[i].l;)
{
ans=max(ans,col[L]);
L--;
}
Q[i].ANS=ans;
L=min(x*fk,n)+1;
ans=fy;
RET++;
}
return RET;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&col[i]);
}
fk=sqrt(n);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].place=i;
}
for(int i=1;i<=n;i++)
{
FK[i]=(i-1)/fk+1;
}
sort(Q+1,Q+m+1,cmp);
int now=1;
for(int i=1;i<=FK[n];i++)
{
now=md(i,now);
}
sort(Q+1,Q+m+1,Cmp);
for(int i=1;i<=m;i++)
{
printf("%d\n",Q[i].ANS);
}
}