[国家集训队][bzoj2038] 小Z的袜子 [莫队]

题面:

传送门

思路:

又是一道标准的莫队处理题目,但是这道题需要一点小改动:求个数变成了求概率

我们思考:每次某种颜色从i个增加到i+1个,符合要求的情况多了多少?

原来的总情况数是i*(i-1)/2,现在是i*(i+1)/2,实际上就是增加了i个!

所以我们只要把对答案tot的更改变成加i即可

莫队学习请戳这里:莫队

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define ll long long
 7 using namespace std;
 8 inline ll read(){
 9     ll re=0,flag=1;char ch=getchar();
10     while(ch>'9'||ch<'0'){
11         if(ch=='-') flag=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
15     return re*flag;
16 }
17 ll n,m,cnt[100010],tot=0,x[50010],curl,curr,block;
18 ll sqr[100010],ans[100010],bot[100010];
19 struct query{
20     ll l,r,i;
21 }a[100010];
22 bool cmp(query l,query r){
23     if(l.l/block!=r.l/block) return (l.l/block)<(r.l/block);
24     else return l.r<r.r;
25 }
26 void add(ll i){
27     cnt[x[i]]++;tot+=sqr[cnt[x[i]]]-sqr[cnt[x[i]]-1];
28     //cout<<"add "<<i<<" "<<x[i]<<" "<<cnt[x[i]]<<"\n";
29 }
30 void erase(ll i){
31     cnt[x[i]]--;tot+=sqr[cnt[x[i]]]-sqr[cnt[x[i]]+1];
32     //cout<<"erase "<<i<<" "<<x[i]<<" "<<cnt[x[i]]<<"\n";
33 }
34 void init(){
35     for(ll i=1;i<=n;i++) sqr[i]=i*(i-1);
36 }
37 ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
38 int main(){
39     ll i;ll tmp,t1,t2;
40     n=read();m=read();for(i=1;i<=n;i++) x[i]=read();block=sqrt(n);
41     init();
42     for(i=1;i<=m;i++) a[i].l=read(),a[i].r=read(),a[i].i=i;
43     sort(a+1,a+m+1,cmp);curl=a[1].l;curr=a[1].r;
44     for(i=a[1].l;i<=a[1].r;i++) add(i);
45     ans[a[1].i]=tot;bot[a[1].i]=(a[1].r-a[1].l)*(a[1].r-a[1].l+1);
46     if(a[1].l==a[1].r) bot[a[1].i]=1;
47     for(i=2;i<=m;i++){
48         while(curl<a[i].l) erase(curl++);
49         while(curl>a[i].l) add(--curl);
50         while(curr<a[i].r) add(++curr);
51         while(curr>a[i].r) erase(curr--);
52         ans[a[i].i]=tot;bot[a[i].i]=(a[i].r-a[i].l)*(a[i].r-a[i].l+1);
53         if(a[i].l==a[i].r) bot[a[i].i]=1;
54         //cout<<"now "<<tot<<" "<<a[i].l<<" "<<a[i].r<<"\n";
55     }
56     for(i=1;i<=m;i++){
57         if(ans[i]==0) printf("0/1\n");
58         else{
59             tmp=gcd(bot[i],ans[i]);
60             //cout<<"gcd "<<tmp<<" "<<ans[i]<<" "<<bot[i]<<"\n";
61             t1=ans[i]/tmp;t2=bot[i]/tmp;
62             printf("%lld/%lld\n",t1,t2);
63         }
64     } 
65 }

 

posted @ 2018-03-04 08:57  dedicatus545  阅读(177)  评论(0编辑  收藏  举报