zoukankan      html  css  js  c++  java
  • bzoj1878

    像我这种蒟蒻这道题从在线算法思考基本毫无思路

    但是发现题目中只涉及到询问而不涉及到修改,这类题目一般都是离线算法大概

    考虑到这题为什么不能直接区间求值,因为区间中同色点会被重复计算(废话)

    下面我们就要通过离线算法来排除区间内同色点干扰

    首先想到对询问区间以左端点排序,

    考虑到区间内的同色点我们只要算最左边的就行了

    先将每种颜色第一次出现的位置标记为1

    然后从左往右扫描每一个位置,算出以这个位置为左端点的区间答案(区间和)

    然后再将这个位置颜色的下一个同色位置标记

    这样我们就保证了每次区间询问,同色点只算了一遍

    因为一个区间内要么不存在同色点,

    要么同色点只出现了一次(被标记了一次),下一个同色点一定还没有标记,而上一个同色点一定在区间外左侧

    语言表述不太好,具体还是看程序吧……

     1 var a,c,next:array[0..60010] of longint;
     2     x,y,ans,p:array[0..200010] of longint;
     3     last:array[0..1000000] of longint;
     4     max,i,n,m,j:longint;
     5 function lowbit(x:longint):longint;
     6   begin
     7     exit(x and(-x));
     8   end;
     9 
    10 function sum(x:longint):longint;
    11   begin
    12     sum:=0;
    13     while x<>0 do
    14     begin
    15       sum:=sum+c[x];
    16       x:=x-lowbit(x);
    17     end;
    18   end;
    19 
    20 procedure add(x:longint);
    21   begin
    22     while x<=n do
    23     begin
    24       inc(c[x]);
    25       x:=x+lowbit(x);
    26     end;
    27   end;
    28 
    29 procedure swap(var a,b:longint);
    30   var c:longint;
    31   begin
    32     c:=a;
    33     a:=b;
    34     b:=c;
    35   end;
    36 
    37 procedure sort(l,r: longint);
    38   var i,j,z: longint;
    39   begin
    40     i:=l;
    41     j:=r;
    42     z:=x[(l+r) div 2];
    43     repeat
    44       while x[i]<z do inc(i);
    45       while z<x[j] do dec(j);
    46       if not(i>j) then
    47       begin
    48         swap(x[i],x[j]);
    49         swap(y[i],y[j]);
    50         swap(p[i],p[j]);
    51         inc(i);
    52         dec(j);
    53       end;
    54     until i>j;
    55     if l<j then sort(l,j);
    56     if i<r then sort(i,r);
    57   end;
    58 
    59 begin
    60   readln(n);
    61   for i:=1 to n do
    62   begin
    63     read(a[i]);
    64     if max<a[i] then max:=a[i];
    65   end;
    66   readln(m);
    67   for i:=1 to m do
    68   begin
    69     readln(x[i],y[i]);
    70     p[i]:=i;
    71   end;
    72   sort(1,m);
    73   fillchar(last,sizeof(last),0);
    74   for i:=n downto 1 do  //计算每个位置下一个同色点的位置
    75   begin
    76     next[i]:=last[a[i]];
    77     last[a[i]]:=i;
    78   end;
    79   for i:=1 to max do   //先映射每种颜色第一次出现的位置
    80     if last[i]<>0 then add(last[i]);
    81 
    82   j:=1;
    83   for i:=1 to n do
    84   begin
    85     while x[j]=i do
    86     begin
    87       ans[p[j]]:=sum(y[j])-sum(x[j]-1);
    88       inc(j);
    89     end;
    90     if next[i]<>0 then add(next[i]);
    91   end;
    92   for i:=1 to m do
    93     writeln(ans[i]);
    94 end.
    View Code
  • 相关阅读:
    LQB201803乘积尾零
    最大公约数
    快速幂运算
    二分法查找原理
    递归-24点
    递归-爬楼梯
    递归-中项表达式求解
    IDEA的安装基本使用
    SSM和开源框架 ------面试指导
    JDK 8 新特性
  • 原文地址:https://www.cnblogs.com/phile/p/4473184.html
Copyright © 2011-2022 走看看