1. 程式人生 > >[bzoj2038]莫隊算法學習

[bzoj2038]莫隊算法學習

ace stream += include clu con typedef code ios

解題關鍵:莫隊最重要的是區間之間以$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]莫隊算法學習