[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 }