题解:
区间总的方案数是可以算的,只要求相同的颜色的方案数即可。(数学中讲的古典概型??)
我不知道我写的是不是莫队算法,时间还是很快的。。
话说,这题稍微优化的暴力也能过。
看了别人的介绍莫队算法的文章没有看太懂,也不知道这个神奇的复杂度是怎么证明的。。。
我大致是这样做的:
1、分块
2、把所有询问左端点排序
3、对于左端点在同一块内的询问按右端点排序,然后分三种情况统计。
传说中这样复杂度是nsqrt(n)的,但是我怎么觉得这个和我的暴力差不多。。。。
莫名其妙跑的这么快。。。

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <cmath> 7 8 #define N 55555 9 10 using namespace std; 11 12 struct Q 13 { 14 long long l,r,id; 15 }q[N]; 16 17 struct ANS 18 { 19 long long a,b; 20 void in(long long x,long long y) {a=x,b=y;} 21 }ans[N]; 22 23 long long col[N],n,m,gs[N]; 24 long long lt[N],rt[N],len,tot; 25 26 inline bool cmpl(const Q &a,const Q &b) 27 { 28 return a.l<b.l; 29 } 30 31 inline bool cmpr(const Q &a,const Q &b) 32 { 33 return a.r<b.r; 34 } 35 36 inline void read() 37 { 38 scanf("%lld%d",&n,&m); 39 for(long long i=1;i<=n;i++) scanf("%lld",&col[i]); 40 for(long long i=1;i<=m;i++) 41 { 42 scanf("%lld%d",&q[i].l,&q[i].r); 43 q[i].id=i; 44 } 45 len=(long long)sqrt(1.0*n); 46 tot=n/len; 47 for(long long i=1;i<=tot;i++) lt[i]=rt[i-1]+1,rt[i]=rt[i-1]+len; 48 if(rt[tot]!=n) lt[tot+1]=rt[tot]+1,rt[tot+1]=n,tot++; 49 } 50 51 inline long long gcd(long long x,long long y) 52 { 53 long long ys; 54 while(y) 55 { 56 ys=x%y; 57 x=y; y=ys; 58 } 59 return x; 60 } 61 62 inline void getans(long long x,long long ml) 63 { 64 long long sum=(q[x].r-q[x].l)*(q[x].r-q[x].l+1)/2; 65 long long mx=gcd(ml,sum); 66 if(!mx) ans[q[x].id].in(0,1); 67 else ans[q[x].id].in(ml/mx,sum/mx); 68 } 69 70 inline void go() 71 { 72 sort(q+1,q+m+1,cmpl); 73 long long s=1,t=1; 74 for(long long i=1,ml=0;i<=tot;i++,ml=0) 75 { 76 memset(gs,0,sizeof gs); 77 while(s<=m&&q[s].l<lt[i]) s++; 78 while(t<=m&&q[t].l<=rt[i]) t++; 79 if(s>m||q[s].l>rt[i]) continue; 80 sort(q+s,q+t,cmpr); 81 for(long long j=q[s].l;j<=q[s].r;j++) ml+=gs[col[j]],gs[col[j]]++; 82 getans(s,ml); 83 for(long long j=s+1;j<t;j++) 84 { 85 if(q[j].l<q[j-1].l) 86 { 87 for(long long k=q[j].l;k<q[j-1].l;k++) ml+=gs[col[k]],gs[col[k]]++; 88 for(long long k=q[j-1].r+1;k<=q[j].r;k++) ml+=gs[col[k]],gs[col[k]]++; 89 } 90 else if(q[j].l>q[j-1].r) 91 { 92 for(long long k=q[j-1].l;k<=q[j-1].r;k++) gs[col[k]]--; 93 ml=0; 94 for(long long k=q[j].l;k<=q[j].r;k++) ml+=gs[col[k]],gs[col[k]]++; 95 } 96 else 97 { 98 for(long long k=q[j-1].l;k<q[j].l;k++) gs[col[k]]--,ml-=gs[col[k]]; 99 for(long long k=q[j-1].r+1;k<=q[j].r;k++) ml+=gs[col[k]],gs[col[k]]++; 100 } 101 getans(j,ml); 102 } 103 } 104 for(long long i=1;i<=m;i++) printf("%lld/%lld\n",ans[i].a,ans[i].b); 105 } 106 107 int main() 108 { 109 read(),go(); 110 return 0; 111 }
这个莫队算法是处理区间无修改询问的通用算法??