zoukankan      html  css  js  c++  java
  • bzoj2120 2453

    明显的数据结构题
    这道题的特殊性在于n只有10000,修改的操作只有1000
    那么就是说即便是O(n)的修改也没有太大的问题,只要常数写小一点即可
    考虑到以前对同色点的处理
    pre[i]表示与这个位置同色的前一个位置
    对于一段区间l,r,如果区间中位置i,满足pre[i]<l则这个位置上的颜色是一种,被算一次
    直接扫描显然O(n),但假如这段位置pre有序,我们就可以用二分
    但是如果整体排序我们就不好确定区间的位置
    因此我们考虑分块,每块内pre排序,当查询区间[l,r]时
    先暴力统计l,r所在块内,在用二分统计在l,r所在块之间的块每块中符合条件的个数
    这样的复杂度还是可以接受了
    然后考虑修改,首先修改只会对原来颜色和修改成颜色的位置产生影响
    我们只要找到原来颜色的下一个同色点位置并修改所在块,
    并且找到现在颜色的下一个同色点位置并修改所在块
    当然这个位置的所在块也是要修改的

      1 var p,pre,b,a:array[0..10010] of longint;
      2     v:array[0..10010] of boolean;
      3     last:array[0..1000010] of longint;
      4     t,n,m,size,i,x,y:longint;
      5     ch:char;
      6 
      7 procedure sort(l,r: longint);
      8   var i,j,x,y: longint;
      9   begin
     10     i:=l;
     11     j:=r;
     12     x:=b[(l+r) div 2];
     13     repeat
     14       while b[i]<x do inc(i);
     15       while x<b[j] do dec(j);
     16       if not(i>j) then
     17       begin
     18         y:=b[i];
     19         b[i]:=b[j];
     20         b[j]:=y;
     21         inc(i);
     22         j:=j-1;
     23       end;
     24     until i>j;
     25     if l<j then sort(l,j);
     26     if i<r then sort(i,r);
     27   end;
     28 
     29 function find(x,y:longint):longint;
     30   var l,r,m,f:longint;
     31   begin
     32     l:=(x-1)*size+1;
     33     f:=l;
     34     r:=x*size;
     35     if r>n then r:=n;
     36     while l<=r do
     37     begin
     38       m:=(l+r) shr 1;
     39       if b[m]<y then l:=m+1
     40       else r:=m-1;
     41     end;
     42     exit(l-f);
     43   end;
     44 
     45 function ask(l,r:longint):longint;
     46   var i:longint;
     47   begin
     48     ask:=0;
     49     if p[l]=p[r] then
     50     begin
     51       for i:=l to r do   //l,r在一个块
     52         if pre[i]<l then inc(ask);
     53     end
     54     else begin          //不在一个块
     55       for i:=l to p[l]*size do
     56         if pre[i]<l then inc(ask);  
     57       for i:=(p[r]-1)*size+1 to r do
     58         if pre[i]<l then inc(ask);
     59       for i:=p[l]+1 to p[r]-1 do
     60         ask:=ask+find(i,l);   
     61     end;
     62   end;
     63 
     64 procedure build(x:longint);
     65   var l,r,i:longint;
     66   begin
     67     l:=(x-1)*size+1;
     68     r:=x*size;
     69     if r>n then r:=n;
     70     for i:=l to r do
     71       b[i]:=pre[i];   //另开一个数组排序方便二分
     72     sort(l,r);
     73   end;
     74 
     75 procedure change(x,y:longint);
     76   var i,j,k:longint;
     77   begin
     78     if a[x]=y then exit;
     79     fillchar(v,sizeof(v),false);
     80     i:=last[a[x]];
     81     k:=pre[x];
     82     v[p[x]]:=true;
     83     j:=0;
     84     while i<>x do
     85     begin
     86       j:=i;
     87       i:=pre[i];
     88     end;
     89     if j<>0 then
     90     begin
     91       pre[j]:=k;
     92       v[p[j]]:=true;    //原来颜色的下一个同色点的位置所在块要修改
     93     end
     94     else last[a[x]]:=pre[i];  //如果是原来颜色的最后一个位置
     95 
     96     a[x]:=y;
     97     i:=last[y];
     98     if x>i then         //如果是现在颜色的最后一个位置
     99     begin
    100       last[y]:=x;
    101       pre[x]:=i
    102     end
    103     else begin
    104       while not((pre[i]<x) and (x<i)) do i:=pre[i];
    105       pre[x]:=pre[i];  //在现在颜色的链上上插入这个位置
    106       v[p[i]]:=true;   //现在颜色的下一个同色点所在位置要修改
    107       pre[i]:=x;
    108     end;
    109     for i:=1 to t do
    110       if v[i] then build(i);
    111   end;
    112 
    113 begin
    114   readln(n,m);
    115   for i:=1 to n do
    116     read(a[i]);
    117   readln;
    118   size:=trunc(sqrt(n)+ln(2*n)/ln(2));  //因为查询的复杂度带了一个logn,所以块的大小这样合适
    119   fillchar(last,sizeof(last),255);
    120   t:=1;
    121   for i:=1 to n do
    122   begin
    123     p[i]:=t;          //每个位置所在块的编号
    124     pre[i]:=last[a[i]];
    125     last[a[i]]:=i;
    126     if i mod size=0 then inc(t);
    127   end;
    128   if n mod size=0 then dec(t);
    129   for i:=1 to t do
    130     build(i);
    131 
    132   for i:=1 to m do
    133   begin
    134     readln(ch,x,y);
    135     if ch='Q' then writeln(ask(x,y))
    136     else change(x,y);
    137   end;
    138 end.
    View Code
  • 相关阅读:
    css3
    My97DatePicker时间控件使用
    练习中遇到的问题及知识点
    使用slideDown和slideUp做二级菜单时遇到的bug解决方法
    Google Chrome浏览器不支持小于12px的字体大小的问题及解决方法(我写的都不行)
    区别不同浏览器的兼容性
    img图片元素下多余空白解决方案
    gridview列绑定HyperLink
    vs设计界面出现“建控件时出错 响应在此上下文中不可用”
    SQL Server不能通过外部IP访问,解决方法
  • 原文地址:https://www.cnblogs.com/phile/p/4473117.html
Copyright © 2011-2022 走看看