【BZOJ2038】小Z的袜子(莫队)
题意:
给定n个数a1, a2…… an与m个询问(L,R)。对于每个询问,从aL, aL+1…… aR这R-L+1个数中随机取出两个数,求这两个数相同的概率。
数据范围:1<=n,m,ai<=50000
思路:
以下是原话:
平方运算的存在是线段树无法打破的坚冰!
只有询问,没有修改! 可以任意的顺序求解询问!
考虑两个位置关系任意的区间[L1,R1]与[L2,R2]
已有前者的信息,要得到后者的信息只需插入或删除L1与L2间的数和R1与R2间的数
若L1<L2则删除[L1,L2-1]内的数, 否则插入[L2,L1-1]内的数;
若R1<R2则插入[R1+1,R2]内的数, 否则删除[R2+1,R1]内的数;
无论何种情况,所需操作数均为 |L1 - L2| + |R1 - R2|
将m个区间重新排列,最小化:
定义(L0,R0) = (1,0)
分块,将询问以左端点所在块的编号为第一关键字,右端点大小为第二关键字排序,依次计算保证
时间复杂度O(N^1.5)
复杂度分析是这样的:
1、i与i+1在同一块内,r单调递增,所以r是O(n)的。由于有n^0.5块,所以这一部分时间复杂度是n^1.5。
2、i与i+1跨越一块,r最多变化n,由于有n^0.5块,所以这一部分时间复杂度是n^1.5
3、i与i+1在同一块内时l变化不超过n^0.5,跨越一块也不会超过n^0.5,忽略*2。由于有m次询问(和n同级),所以时间复杂度是n^1.5
于是就是O(n^1.5)了
1 type arr=record 2 l,r,c,t:longint; 3 end; 4 var s:array[0..50000]of int64; 5 ans:array[1..50000,1..2]of int64; 6 q:array[1..50000]of arr; 7 c,a:array[1..50000]of longint; 8 n,m,i,kuai:longint; 9 tmp:int64; 10 11 procedure swap(var x,y:arr); 12 var t:arr; 13 begin 14 t:=x; x:=y; y:=t; 15 end; 16 17 procedure qsort(l,r:longint); 18 var i,j,mid1,mid2:longint; 19 begin 20 i:=l; j:=r; mid1:=q[(l+r)>>1].c; mid2:=q[(l+r)>>1].r; 21 repeat 22 while (mid1>q[i].c)or((mid1=q[i].c)and(mid2>q[i].r)) do inc(i); 23 while (mid1<q[j].c)or((mid1=q[j].c)and(mid2<q[j].r)) do dec(j); 24 if i<=j then 25 begin 26 swap(q[i],q[j]); 27 inc(i); dec(j); 28 end; 29 until i>j; 30 if l<j then qsort(l,j); 31 if i<r then qsort(i,r); 32 end; 33 34 function gcd(x,y:int64):int64; 35 var r,t:int64; 36 begin 37 if x<y then 38 begin 39 t:=x; x:=y; y:=t; 40 end; 41 repeat 42 r:=x mod y; 43 x:=y; 44 y:=r; 45 until r=0; 46 exit(x); 47 end; 48 49 procedure add(x,y:longint); 50 begin 51 tmp:=tmp-s[a[x]]*s[a[x]]; 52 s[a[x]]:=s[a[x]]+y; 53 tmp:=tmp+s[a[x]]*s[a[x]]; 54 end; 55 56 procedure modui; 57 var a,b,c,d,k1,k2,k:int64; 58 i,j:longint; 59 begin 60 a:=1; b:=0; tmp:=0; 61 for i:=1 to m do 62 begin 63 c:=q[i].l; d:=q[i].r; 64 for j:=b+1 to d do add(j,1); 65 for j:=c to a-1 do add(j,1); 66 for j:=a to c-1 do add(j,-1); 67 for j:=d+1 to b do add(j,-1); 68 a:=c; b:=d; 69 if c=d then 70 begin 71 ans[i,1]:=0; ans[i,2]:=1; 72 continue; 73 end; 74 k1:=tmp-(d-c+1); 75 if k1=0 then 76 begin 77 ans[i,1]:=0; ans[i,2]:=1; 78 continue; 79 end; 80 k2:=(d-c+1)*(d-c); 81 k:=gcd(k1,k2); 82 ans[i,1]:=k1 div k; 83 ans[i,2]:=k2 div k; 84 end; 85 86 end; 87 88 procedure qsort1(l,r:longint); 89 var i,j,mid:longint; 90 t:int64; 91 begin 92 i:=l; j:=r; mid:=q[(l+r)>>1].t; 93 repeat 94 while mid>q[i].t do inc(i); 95 while mid<q[j].t do dec(j); 96 if i<=j then 97 begin 98 swap(q[i],q[j]); 99 t:=ans[i,1]; ans[i,1]:=ans[j,1]; ans[j,1]:=t; 100 t:=ans[i,2]; ans[i,2]:=ans[j,2]; ans[j,2]:=t; 101 inc(i); dec(j); 102 end; 103 until i>j; 104 if l<j then qsort1(l,j); 105 if i<r then qsort1(i,r); 106 end; 107 108 begin 109 assign(input,'bzoj2038.in'); reset(input); 110 assign(output,'bzoj2038.out'); rewrite(output); 111 readln(n,m); 112 for i:=1 to n do read(a[i]); 113 kuai:=trunc(sqrt(n)); 114 for i:=1 to n do c[i]:=(i-1) div kuai+1; 115 for i:=1 to m do 116 begin 117 readln(q[i].l,q[i].r); 118 q[i].c:=c[q[i].l]; 119 q[i].t:=i; 120 end; 121 qsort(1,m); 122 modui; 123 qsort1(1,m); 124 for i:=1 to m do writeln(ans[i,1],'/',ans[i,2]); 125 close(input); 126 close(output); 127 end.
null