标签:span var cts set 部分 sig 莫队算法 .com size
复杂度分析
莫队算法
如果我们已知[l,r]的答案,能在O(1)时间得到[l+1,r]的答案以及[l,r-1]的答案,即可使用莫队算法。时间复杂度为O(n^1.5)。如果只能在logn的时间移动区间,
则时间复杂度是O(n^1.5*log n)。
其实就是找一个数据结构支持插入、删除时维护当前答案。
这道题的话我们很容易用数组来实现,做到O(1)的从[l,r]转移到[l,r+1]与[l+1,r]。
那么莫队算法怎么做呢?以下都是在转移为O(1)的基础下讨论的时间复杂度。另外由于n与m同阶,就统一写n。
如果已知[l,r]的答案,要求[l’,r’]的答案,我们很容易通过|l – l’|+|r – r’|次转移内求得。
将n个数分成sqrt(n)块。
按区间排序,以左端点所在块内为第一关键字,右端点为第二关键字,进行排序,也就是以(pos [l],r)排序
然后按这个排序直接暴力,复杂度分析是这样的:
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)了
没有进一步进行化简 (a*a-1)/2
type node=record l,r:longint; end; var a,k,opp:array[0..1000000]of longint; q,ju:array[1..1000000]of node; n,m,s,i,j,gg:longint; ans:node; function change(num:longint):longint; begin if num mod s=0 then exit(num div s) else exit(num div s+1); end; function gcd(p,q:longint):longint; begin if p mod q=0 then exit(q); exit(gcd(q,p mod q)); end; procedure qsort(l,r:longint); var i,j,z:longint; x,y:node; begin i:=l; j:=r; x:=q[(l+r)div 2]; repeat while(change(q[i].l)<change(x.l))or (change(q[i].l)=change(x.l))and(q[i].r<x.r)do inc(i); while(change(x.l)<change(q[j].l))or (change(x.l)=change(q[j].l))and(x.r<q[j].r)do dec(j); if not(i>j) then begin y:=q[i]; q[i]:=q[j]; q[j]:=y; z:=opp[i]; opp[i]:=opp[j]; opp[j]:=z; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; begin ans.l:=0; ans.r:=0; readln(n,m); for i:=1 to n do read(a[i]); readln; for i:=1 to m do readln(q[i].l,q[i].r); for i:=1 to m do opp[i]:=i; s:=round(sqrt(n)); qsort(1,m); for i:=q[1].l to q[1].r do begin //if(k[a[i]]=0)then inc(ans); inc(ans.l,k[a[i]]); inc(k[a[i]]); end; //ju[opp[1]]:=ans; ans.r:=(q[1].r-q[1].l+1)*(q[1].r-q[1].l)div 2; ju[opp[1]]:=ans; for i:=2 to m do begin if(q[i].l<q[i-1].l)then for j:=q[i].l to q[i-1].l-1 do begin //if(k[a[j]]=0)then inc(ans); inc(ans.l,k[a[j]]); inc(k[a[j]]); end; if(q[i].r>q[i-1].r)then for j:=q[i-1].r+1 to q[i].r do begin //if(k[a[j]]=0)then inc(ans); inc(ans.l,k[a[j]]); inc(k[a[j]]); end; if(q[i].l>q[i-1].l)then for j:=q[i-1].l to q[i].l-1 do begin dec(k[a[j]]); dec(ans.l,k[a[j]]); //if(k[a[j]]=0)then dec(ans); end; if(q[i].r<q[i-1].r)then for j:=q[i].r+1 to q[i-1].r do begin dec(k[a[j]]); dec(ans.l,k[a[j]]); //if(k[a[j]]=0)then dec(ans); end; //ju[opp[i]]:=ans; ans.r:=(q[i].r-q[i].l+1)*(q[i].r-q[i].l)div 2; ju[opp[i]]:=ans; end; //for i:=1 to m do writeln(ju[i]); for i:=1 to m do begin if ju[i].l=0 then begin writeln(‘0/1‘); continue; end; gg:=gcd(ju[i].l,ju[i].r); ju[i].l:=ju[i].l div gg; ju[i].r:=ju[i].r div gg; writeln(ju[i].l,‘/‘,ju[i].r); end; end.
化简后ac
// luogu-judger-enable-o2 // luogu-judger-enable-o2 type ZTYAK_NOIP_POI_NOI_IOI_ACMWorldFinal_WC_CTSC=record ans1,ans2:int64; end; type ZTYAK_ACMWorldFinal_WC_CTSC=record l,r:int64; end; var a:array[0..400005]of ZTYAK_ACMWorldFinal_WC_CTSC; q:array[0..400005]of ZTYAK_NOIP_POI_NOI_IOI_ACMWorldFinal_WC_CTSC; sum,d,id:array[0..400005]of longint; n,m,i,left,right,kuai,tt:longint; ans,t:int64; function size(x:longint):longint; begin exit(x div kuai+1); end; procedure qsort(l,r:longint); var i,j,k,t2:longint; t:ZTYAK_ACMWorldFinal_WC_CTSC; begin i:=l; j:=r; k:=(i+j) div 2; t:=a[k]; t2:=id[k]; a[k]:=a[i]; id[k]:=id[i]; while i<j do begin while (i<j) and ((size(a[j].l)<>size(t.l)) and (a[j].l>t.l) or (size(a[j].l)=size(t.l)) and (a[j].r>t.r)) do dec(j); {while (i<J) and (a[j].l>t.l) do dec(j);} if i<j then begin a[i]:=a[j]; id[i]:=id[j]; inc(i); end; while (i<j) and ((size(a[i].l)<>size(t.l)) and (a[i].l<t.l) or (size(a[i].l)=size(t.l)) and (a[i].r<t.r)) do inc(i); {while (i<J) and (a[i].l<t.l) do inc(i);} if i<j then begin a[j]:=a[i]; id[j]:=id[i]; dec(j); end; end; a[i]:=t; id[i]:=t2; if i-1>l then qsort(l,i-1); if i+1<r then qsort(i+1,r); end; procedure rev(x,y:longint); begin ans:=ans-sqr(sum[d[x]]); sum[d[x]]:=sum[d[x]]+y; ans:=ans+sqr(sum[d[x]]); end; function gcd(x,y:int64):int64; begin if x mod y=0 then exit(y); exit(gcd(y,x mod y)); end; begin //assign(input,‘7.in‘); reset(input); //assign(output,‘77.out‘); rewrite(output); readln(n,m); kuai:=trunc(sqrt(n)); for i:=1 to n do read(d[i]); readln; for i:=1 to m do begin readln(a[i].l,a[i].r); if a[i].l>a[i].r then begin tt:=a[i].l; a[i].l:=a[i].r; a[i].r:=tt; end; id[i]:=i; end; qsort(1,m); left:=1; right:=0; {for i:=1 to m do bo[id[i]]:=true;} for i:=1 to m do begin //writeln(id[i]); //bo[id[i]]:=true; while left>a[i].l do begin dec(left); rev(left,1); end; while left<a[i].l do begin rev(left,-1); inc(left); end; while right<a[i].r do begin inc(right); rev(right,1); end; while right>a[i].r do begin rev(right,-1); dec(right); end; if a[i].l=a[i].r then begin q[id[i]].ans1:=0; q[id[i]].ans2:=1; continue; end; q[id[i]].ans1:=ans-(a[i].r-a[i].l+1); q[id[i]].ans2:=(a[i].r-a[i].l+1)*(a[i].r-a[i].l); t:=gcd(q[id[i]].ans1,q[id[i]].ans2); q[id[i]].ans1:=q[id[i]].ans1 div t; q[id[i]].ans2:=q[id[i]].ans2 div t; end; {for i:=1 to m do if not bo[i] then writeln(‘WA‘);} for i:=1 to m do writeln(q[i].ans1,‘/‘,q[i].ans2); //close(input);close(output); end.
70其他三点tle
type qq=record ans1,ans2:int64; end; type aa=record l,r:int64; end; var a:array[0..400005]of aa; q:array[0..400005]of qq; sum,d,id:array[0..400005]of longint; n,m,i,left,right,kuai,tt:longint; ans,t:int64; function size(x:longint):longint; begin exit(x div kuai+1); end; procedure qsort(l,r:longint); var i,j,k,t2:longint; t:aa; begin i:=l; j:=r; k:=(i+j) div 2; while i<j do begin while (size(a[i].l)<size(a[k].l)) or ((size(a[i].l)=size(a[k].l)) and (a[i].r<a[k].r)) do inc(i); while (size(a[j].l)>size(a[k].l)) or ((size(a[j].l)=size(a[k].l)) and (a[j].r>a[k].r)) do dec(j); if i<=j then begin t:=a[i]; a[i]:=a[j]; a[j]:=t; t2:=id[i]; id[i]:=id[j]; id[j]:=t2; inc(i); dec(j); end;end; if j>l then qsort(l,j); if i<r then qsort(i,r); end; procedure rev(x,y:longint); begin ans:=ans-sqr(sum[d[x]]); sum[d[x]]:=sum[d[x]]+y; ans:=ans+sqr(sum[d[x]]); end; function gcd(x,y:int64):int64; begin if x mod y=0 then exit(y); exit(gcd(y,x mod y)); end; begin readln(n,m); kuai:=trunc(sqrt(n)); for i:=1 to n do read(d[i]); readln; for i:=1 to m do begin readln(a[i].l,a[i].r); if a[i].l>a[i].r then begin tt:=a[i].l; a[i].l:=a[i].r; a[i].r:=tt; end; id[i]:=i; end; qsort(1,m); left:=1; right:=0; for i:=1 to m do begin while left>a[i].l do begin dec(left); rev(left,1); end; while left<a[i].l do begin rev(left,-1); inc(left); end; while right<a[i].r do begin inc(right); rev(right,1); end; while right>a[i].r do begin rev(right,-1); dec(right); end; if a[i].l=a[i].r then begin q[id[i]].ans1:=0; q[id[i]].ans2:=1; continue; end; q[id[i]].ans1:=ans-(a[i].r-a[i].l+1); q[id[i]].ans2:=(a[i].r-a[i].l+1)*(a[i].r-a[i].l); t:=gcd(q[id[i]].ans1,q[id[i]].ans2); q[id[i]].ans1:=q[id[i]].ans1 div t; q[id[i]].ans2:=q[id[i]].ans2 div t; end; for i:=1 to m do writeln(q[i].ans1,‘/‘,q[i].ans2); end.
标签:span var cts set 部分 sig 莫队算法 .com size
原文地址:https://www.cnblogs.com/wyh447154317/p/9451325.html