【bzoj2038】小Z的襪子
阿新 • • 發佈:2018-11-02
+= span \n pri 維護 html tro code math
莫隊算法是一種針對詢問進行分塊的離線算法,如果已知區間 [ l , r ] 內的答案,並且可以在 \(O(1)\) 的時間內知道區間 [ l-1, r ],[ l , r+1 ] 的答案,即可使用莫對算法。
莫隊算法維護的是當前區間的答案。
推薦一篇較好的莫隊算法講解文章\(\rightarrow\)莫隊
代碼如下
#include <bits/stdc++.h> using namespace std; const int maxn=5e4+10; struct node{int l,r,id,b;}q[maxn]; int n,m,size,cnt[maxn],a[maxn]; long long ans1[maxn],ans2[maxn]; bool cmp(const node& x,const node& y){return x.b==y.b?x.r<y.r:x.b<y.b;} void read_and_parse(){ scanf("%d%d",&n,&m); size=(int)sqrt(n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].b=(q[i].l-1)/size+1; q[i].id=i; } sort(q+1,q+m+1,cmp); } long long gcd(long long x,long long y){return y?gcd(y,x%y):x;} void solve(){ for(int i=1,lp=1,rp=0,now=0;i<=m;i++){ while(lp<q[i].l)now-=2*cnt[a[lp]]-2,--cnt[a[lp]],++lp; while(rp>q[i].r)now-=2*cnt[a[rp]]-2,--cnt[a[rp]],--rp; while(lp>q[i].l)--lp,now+=2*cnt[a[lp]],++cnt[a[lp]]; while(rp<q[i].r)++rp,now+=2*cnt[a[rp]],++cnt[a[rp]]; if(q[i].l^q[i].r)ans1[q[i].id]=(long long)now,ans2[q[i].id]=(long long)(q[i].r-q[i].l+1)*(q[i].r-q[i].l); else ans1[q[i].id]=0,ans2[q[i].id]=1; } long long com; for(int i=1;i<=m;i++)com=gcd(ans1[i],ans2[i]),printf("%lld/%lld\n",ans1[i]/com,ans2[i]/com); } int main(){ read_and_parse(); solve(); return 0; }
【bzoj2038】小Z的襪子