码迷,mamicode.com
首页 > 其他好文 > 详细

小Z的袜子

时间:2018-08-09 21:16:44      阅读:157      评论:0      收藏:0      [点我收藏+]

标签: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.

 

小Z的袜子

标签:span   var   cts   set   部分   sig   莫队算法   .com   size   

原文地址:https://www.cnblogs.com/wyh447154317/p/9451325.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!