bzoj 2453 && bzoj 2120 分块

来源:互联网 发布:非洲军事 知乎 编辑:程序博客网 时间:2024/05/17 00:16

题意:给定一个序列,支持两种操作:(1)多次询问某个区间所含数字种类数 (2)单点修改

强行分块...

对每个位置维护一个pre数组,表示当前位置颜色的上一个位置

如果pre[i]<l则这个颜色是第一次在这个区间内出现,答案+1

每个块内对pre数组排序,

询问时,在整块里每次二分找到l的严格下界,加到答案里;两边的散块暴力找

对于修改就把影响到的块暴力修改即可..

uses math;var        n,m,q,x,y       :longint;        i               :longint;        ch              :char;        last            :array[0..1000010] of longint;        pre,a,bloc      :array[0..10010] of longint;        num             :array[0..110,0..110] of longint;        flag            :array[0..110] of boolean;procedure sort(x,l,r:longint);var        i,j,y,z:longint;begin   i:=l; j:=r; y:=num[x,(l+r)>>1];   while (i<=j) do   begin      while num[x,i]<y do inc(i);      while num[x,j]>y do dec(j);      if i<=j then      begin         z:=num[x,i]; num[x,i]:=num[x,j]; num[x,j]:=z;         inc(i); dec(j);      end;   end;   if i<r then sort(x,i,r);   if j>l then sort(x,l,j);end;function work(x,y:longint):longint;var        l,r,mid:longint;begin   l:=1; r:=num[x,0];   if num[x,1]>=y then exit(0);   mid:=(l+r+1)>>1;   while (l<r) do   begin      if num[x,mid]<y then l:=mid else r:=mid-1;      mid:=(l+r+1)>>1;   end;   exit(mid);end;function find(a,b:longint):longint;var        ans:longint;        i:longint;begin   ans:=0;   for i:=a to min(bloc[a]*m,b) do     if pre[i]<a then inc(ans);   if bloc[a]<>bloc[b] then     for i:=m*(bloc[b]-1)+1 to b do       if pre[i]<a then inc(ans);   for i:=bloc[a]+1 to bloc[b]-1 do inc(ans,work(i,a));   exit(ans);end;procedure reset(x:longint);var    i:longint;begin   num[x,0]:=0;   for i:=m*(x-1)+1 to min(n,m*x) do   begin      inc(num[x,0]);      num[x,num[x,0]]:=pre[i];   end;   sort(x,1,num[x,0]);end;procedure change(x,y:longint);var        i:longint;        tt:longint;begin   for i:=1 to n do last[a[i]]:=0;   for i:=1 to bloc[n] do flag[i]:=false;   a[x]:=y;   for i:=1 to n do   begin      tt:=last[a[i]];      if tt<>pre[i] then flag[bloc[i]]:=true;      pre[i]:=last[a[i]];      last[a[i]]:=i;   end;   for i:=1 to bloc[n] do     if flag[i] then reset(i);end;begin   read(n,q); m:=trunc(sqrt(n));   for i:=1 to n do   begin      read(a[i]);      pre[i]:=last[a[i]];      last[a[i]]:=i;      bloc[i]:=(i-1) div m+1;   end;   for i:=1 to bloc[n] do reset(i);   //   readln;   for i:=1 to q do   begin      read(ch);      readln(x,y);      if ch='Q' then writeln(find(x,y)) else change(x,y);   end;end.

——by Eirlys


0 0
原创粉丝点击