首页 > 代码库 > [bzoj2038]莫队算法学习

[bzoj2038]莫队算法学习

 

解题关键:莫队最重要的是区间之间以$O(1)$的复杂度进行转化,由于电脑原因,后续补上公式推导。

 

 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<iostream> 6 #include<cmath> 7 using namespace std; 8 typedef long long ll; 9 ll n,m,ans;10 struct node{11     ll l,r,id;12 }b[50002];13 struct nd{14     ll a,b;15 }as[50002];16 ll a[50002],pos[50002],s[50002];17 18 bool cmp1(const node &a,const node &b){19     return ((pos[a.l]==pos[b.l])&&(a.r<b.r))||(pos[a.l]<pos[b.l]);20 }21 22 void init(){23     ll block=sqrt(n);24     for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;25 }26 27 void update(ll p,ll add){28     /*ans-=s[a[p]]*s[a[p]];29     s[a[p]]+=add;30     ans+=s[a[p]]*s[a[p]];*/31     ans+=2*add*s[a[p]]+(add==1?0:2);32     s[a[p]]+=add;33 }34 35 void solve(){36     for(int i=1,l=1,r=0;i<=m;i++){37         for(;r<b[i].r;r++)  update(r+1,1);38         for(;r>b[i].r;r--)  update(r, -1);39         for(;l<b[i].l;l++)  update(l, -1);//这里注意搞清楚40         for(;l>b[i].l;l--)  update(l-1,1);41         if(b[i].l==b[i].r){42             as[b[i].id].a=0,as[b[i].id].b=1;//题目要求43             continue;44         }45         ll c=ans;46         ll d=(b[i].r-b[i].l+1)*(b[i].r-b[i].l);47         ll k=__gcd(c,d);48         c/=k,d/=k;49         as[b[i].id].a=c,as[b[i].id].b=d;50     }51 }52 int main(){53     cin>>n>>m;54     for(int i=1;i<=n;i++) cin>>a[i];55     for(int i=1;i<=m;i++){56         cin>>b[i].l>>b[i].r;57         b[i].id=i;58     }59     init();60     sort(b+1,b+m+1,cmp1);61     solve();62     for(int i=1;i<=m;i++){63         cout<<as[i].a<<"/"<<as[i].b<<"\n";64     }65 }

 

[bzoj2038]莫队算法学习