zoukankan      html  css  js  c++  java
  • [BZOJ2453]维护队列|分块

    Description

    你小时候玩过弹珠吗?
    小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。
     
      思路很简单,在[l,r]中出现过的颜色数量
      我们设b[i]为第i位的数其之前出现的时候的下标
      只要统计在[l,r]间,b[i]<l的数量即可
      
      只要在每次修改的时候维护好b,再每次排序,询问的时候二分查找即可。
      如何维护b呢?
      对于每一个修改,它最多影响两个数的b,一个是它自身,一个是它后面遇到的第一个与它相等的数
      我们只要重新对两个块排序
      但是处理处b,刚开始我想要在每个块中再维护一个以颜色为第一关键字,下标为第二关键字的序列
      对于每个块二分找到修改的点前一次出现的位置 但是感觉十分麻烦
      看了下数据,修改的次数不会超过1000,n<=10000,每次重新算一遍b数组也是可以的
      但是第一次提交TLE了,发现习惯性的fillchar实际上时间并不那么快
      统计b的last数组实际上O(n)赋值比fillchar要快得多(因为last的范围的[0..10^6]啊/w)
      1 program bzoj2453;
      2 const maxn=10010;maxm=1000010;
      3 var n,m,i,block,x,y,q:longint;
      4     ch:char;
      5     pos,a,b,pre:array[-1..maxn]of longint;
      6     last:array[-1..maxm]of longint;
      7 
      8 function min(a,b:longint):longint;
      9 begin
     10     if a<b then exit(a) else exit(b);
     11 end;
     12 
     13 procedure qsort(L,R:longint);
     14 var i,j,mid:longint;
     15 begin
     16     i:=L;j:=R;mid:=pre[random(R-L+1)+L];
     17     repeat
     18         while (i<R)and(pre[i]<mid) do inc(i);
     19         while (L<j)and(pre[j]>mid) do dec(j);
     20         if i<=j then
     21         begin
     22             pre[0]:=pre[i];pre[i]:=pre[j];pre[j]:=pre[0];
     23             inc(i);dec(j);
     24         end;
     25     until i>j;
     26     if i<R then qsort(i,R);
     27     if L<j then qsort(L,j);
     28 end;
     29 
     30 procedure new(x:longint);
     31 var l,r,i:longint;
     32 begin
     33     l:=(x-1)*block+1;r:=min(x*block,n);
     34     for i:=l to r do pre[i]:=b[i];
     35     qsort(l,r);
     36 end;
     37 
     38 procedure change(x,y:longint);
     39 var i:longint;
     40 begin
     41     for i:=1 to n do last[a[i]]:=0;
     42     a[x]:=y;
     43     for i:=1 to n do
     44     begin
     45         if last[a[i]]<>b[i] then
     46                 begin
     47 
     48                 b[i]:=last[a[i]];
     49                         new(pos[i]);
     50                 end;
     51         b[i]:=last[a[i]];
     52         last[a[i]]:=i;
     53     end;
     54 end;
     55 
     56 function find(x,y:longint):longint;
     57 var L,R,mid:longint;
     58 begin
     59     find:=(x-1)*block;
     60     L:=find+1;R:=min(x*block,n);
     61     while L<=R do
     62     begin
     63         mid:=(L+R) >> 1;
     64          if pre[mid]<=y then
     65         begin
     66             find:=mid;L:=mid+1;
     67         end else R:=mid-1;
     68     end;
     69     dec(find,(x-1)*block);
     70 end;
     71 
     72 procedure build;
     73 var i:longint;
     74 begin
     75     for i:=1 to n do last[a[i]]:=0;
     76     for i:=1 to n do
     77     begin
     78         b[i]:=last[a[i]];
     79         last[a[i]]:=i;
     80     end;
     81     for i:=1 to m do new(i);
     82 end;
     83 
     84 function query(x,y:longint):longint;
     85 var i,tot:longint;
     86 begin
     87     tot:=0;
     88     if pos[x]=pos[y] then
     89     begin
     90         for i:=x to y do if b[i]<=x-1 then inc(tot);
     91     end else
     92     begin
     93         for i:=x to pos[x]*block do if b[i]<=x-1 then inc(tot);
     94         for i:=(pos[y]-1)*block+1 to y do if b[i]<=x-1 then inc(tot);
     95         for i:=pos[x]+1 to pos[y]-1 do inc(tot,find(i,x-1));
     96     end;
     97     exit(tot);
     98 end;
     99 
    100 begin
    101     readln(n,q);
    102     block:=trunc(sqrt(n));
    103     for i:=1 to n do
    104     begin
    105         read(a[i]);
    106         pos[i]:=(i-1) div block+1;
    107     end;
    108         readln;
    109     if n mod block=0 then m:=n div block else m:=n div block+1;
    110     build;
    111     for i:=1 to q do
    112     begin
    113         read(ch);
    114         if ch='Q' then
    115         begin
    116             readln(x,y);
    117             writeln(query(x,y));
    118         end else
    119         begin
    120             readln(x,y);
    121             change(x,y);
    122         end;
    123     end;
    124 end.
  • 相关阅读:
    做接口测试最重要的知识点
    HTTP和HTTPS区别
    UVA, 686 Goldbach's Conjecture (II)
    UVA, 543 Goldbach's Conjecture
    UVA, 580 Critical Mass
    UVA, 900 Brick Wall Patterns
    UVA, 11000 Bee
    UVA, 10079 Pizza Cutting
    C++ 向量<vector>的学习
    jenkins入门
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4424266.html
Copyright © 2011-2022 走看看