bzoj2038小z的袜子

来源:互联网 发布:女人都爱用什么软件 编辑:程序博客网 时间:2024/04/25 18:35

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038

分析:

莫队模板题
用分块思想,将询问按开头大小分成sqrt(n)块,然后块内按询问结束排序。
然后暴力从(l,r)转移到(l,r+1)或(l,r-1)或(l-1,r)或(l+1,r)时间为O(1)
时间复杂度分析:
①若转移出现在块内,则块内所有询问之间的转移一共最多需要O(n),一共有n块,所以块内转移时间复杂度一共是O(nlogn)
②若转移出现在块和块之间,则一次块和块之间的转移最多需要O(n),一共有n次这种转移,所以块于块之间的转移时间复杂度一共是O(nlogn)
总时间复杂度为:O(2nlogn)≈O(nlogn)


代码:

type
  node=record
    l,r,id,pos:longint;
  end;
var
  c,cnt:array [1..60001] of int64;
  a:array [1..60001] of node;
  i,j:longint;
  ans,m,n,l,r,k,block,h:int64;


procedure pai1(l,r:longint);
var
  i,j,mid1,mid2:longint;
  t:node;
begin
  i:=l;
  j:=r;
  mid1:=a[(l+r) div 2].pos;
  mid2:=a[(l+r) div 2].r;
  repeat
    while (a[i].pos<mid1) or ((a[i].pos=mid1) and (a[i].r<mid2)) do inc(i);
    while (a[j].pos>mid1) or ((a[j].pos=mid1) and (a[j].r>mid2)) do dec(j);
    if i<=j then
    begin
      t:=a[i];
      a[i]:=a[j];
      a[j]:=t;
      inc(i);
      dec(j);
    end;
  until i>j;
  if l<j then pai1(l,j);
  if i<r then pai1(i,r);
end;


procedure pai2(l,r:longint);
var
  i,j,mid:longint;
  t:node;
begin
  i:=l;
  j:=r;
  mid:=a[(l+r) div 2].id;
  repeat
    while a[i].id<mid do inc(i);
    while a[j].id>mid do dec(j);
    if i<=j then
    begin
      t:=a[i];
      a[i]:=a[j];
      a[j]:=t;
      inc(i);
      dec(j);
    end;
  until i>j;
  if l<j then pai2(l,j);
  if i<r then pai2(i,r);
end;


procedure suan(x,k:longint);
begin
  if k=1 then
  ans:=ans+cnt[c[x]]*(cnt[c[x]]-1) else
  ans:=ans-cnt[c[x]]*(cnt[c[x]]-1);
end;


function gcd(x,y:int64):int64;
begin
  if x mod y=0 then
  exit(y) else
  exit(gcd(y,x mod y));
end;


begin
  assign(input,'sock.in');
  assign(output,'sock.out');
  reset(input);
  rewrite(output);


  readln(n,m);
  for i:=1 to n do
  read(c[i]);
  readln;
  block:=trunc(sqrt(n));
  for i:=1 to m do
  begin
    a[i].id:=i;
    readln(a[i].l,a[i].r);
    a[i].pos:=(a[i].l-1) div block+1;
  end;
  pai1(1,m);
  l:=1;
  r:=0;
  for i:=1 to m do
  begin
    if a[i].l=a[i].r then
    begin
      a[i].l:=0;
      a[i].r:=1;
      continue;
    end;
    while r<a[i].r do
    begin
      inc(r);
      suan(r,2);
      inc(cnt[c[r]]);
      suan(r,1);
    end;
    while r>a[i].r do
    begin
      suan(r,2);
      dec(cnt[c[r]]);
      suan(r,1);
      dec(r);
    end;
    while l<a[i].l do
    begin
      suan(l,2);
      dec(cnt[c[l]]);
      suan(l,1);
      inc(l);
    end;
    while l>a[i].l do
    begin
      dec(l);
      suan(l,2);
      inc(cnt[c[l]]);
      suan(l,1);
    end;
    h:=(a[i].r-a[i].l+1);
    h:=h*(a[i].r-a[i].l);
    k:=gcd(ans,h);
    a[i].r:=h div k;
    a[i].l:=ans div k;
  end;
  pai2(1,m);
  for i:=1 to m do
  writeln(a[i].l,'/',a[i].r);


  close(input);
  close(output);
end.


数据:http://download.csdn.net/detail/boyxiejunboy/9423250

0 0