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

 

posted @ 2017-08-09 23:14  Elpsywk  阅读(149)  评论(0编辑  收藏  举报