• BZOJ1878:[SDOI2009]HH的项链


    Description

    HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。

    Input

    第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

    Output

    M行,每行一个整数,依次表示询问对应的答案。

    Sample Input

    6
    1 2 3 4 3 5
    3
    1 2
    3 5
    2 6

    Sample Output

    2
    2
    4

    HINT

    对于20%的数据,N ≤ 100,M ≤ 1000;
    对于40%的数据,N ≤ 3000,M ≤ 200000;
    对于100%的数据,N ≤ 50000,M ≤ 200000。

    题解:

    用last[i]记录上一个与i号贝壳相同的贝壳所在位置。对于一段区间[l,r],求出其中满足last[i]<l的i的个数,即为答案。

    用线段树记录last为0~n-1的贝壳的个数,因为每加入一个贝壳,只会改变last[0~n-1]中的一个,所以可以用可持久化线段树维护

    代码:

     1 var
     2   i,j,k,n,m,cnt,xx,yy:longint;
     3   pre,root:array[1..50001]of longint;
     4   last:array[0..1000000]of longint;
     5   t:array[1..3000000,-2..2]of longint;
     6 function qq(x,l,r:longint):longint;
     7 var ll,rr:longint;
     8 begin
     9   if(t[x,1]=l)and(t[x,2]=r)then exit(t[x,0]);
    10   ll:=t[x,-1]; rr:=t[x,-2];
    11   if r<=(t[x,1]+t[x,2])div 2 then exit(qq(ll,l,r));
    12   if l>(t[x,1]+t[x,2])div 2 then exit(qq(rr,l,r));
    13   exit(qq(ll,l,t[ll,2])+qq(rr,t[rr,1],r));
    14 end;
    15 procedure build(l,r,x:longint);
    16 var k:longint;
    17 begin
    18   k:=cnt; t[k,1]:=l; t[k,2]:=r; 
    19   if l=r then begin if l=x then t[k,0]:=1; exit; end;
    20   inc(cnt); t[k,-1]:=cnt; build(l,(l+r)div 2,x);
    21   inc(cnt); t[k,-2]:=cnt; build(((l+r)div 2)+1,r,x);
    22   t[k,0]:=t[t[k,-1],0]+t[t[k,-2],0];
    23 end;
    24 procedure newtree(l,r,x,y:longint);
    25 var k:longint;
    26 begin
    27   k:=cnt; t[k,1]:=l; t[k,2]:=r;
    28   if l=r then begin t[k,0]:=t[y,0]; if l=x then inc(t[k,0]); exit; end;
    29   if x<=(l+r)div 2 then
    30   begin
    31     t[k,-2]:=t[y,-2];
    32     inc(cnt); t[k,-1]:=cnt; newtree(l,(l+r)div 2,x,t[y,-1]);
    33   end else
    34   begin
    35     t[k,-1]:=t[y,-1];
    36     inc(cnt);  t[k,-2]:=cnt; newtree(((l+r)div 2)+1,r,x,t[y,-2]);
    37   end;
    38   t[k,0]:=t[t[k,-1],0]+t[t[k,-2],0];
    39 end;
    40 begin
    41   readln(n);
    42   for i:=1 to n do 
    43   begin
    44     read(j); pre[i]:=last[j]; last[j]:=i;
    45   end;
    46   root[1]:=1; cnt:=1;
    47   build(0,n,pre[1]);
    48   for i:=2 to n do
    49   begin
    50     inc(cnt); root[i]:=cnt;
    51     newtree(0,n,pre[i],root[i-1]);
    52   end;
    53   readln(m);
    54   for i:=1 to m do
    55   begin
    56     readln(j,k);
    57     if j=1 then xx:=0 else xx:=qq(root[j-1],0,j-1);
    58     if k=0 then yy:=0 else yy:=qq(root[k],0,j-1);
    59     writeln(yy-xx);
    60   end;
    61 end.
    View Code
  • 相关阅读:
    十四、内存泄露和强软弱虚引用
    十五、对象的内存布局
    Android Service全解(三)之 Foreground Service(转)
    android中不同activity的传参调用和返回
    Android Service全解(一)之 startService(转)
    Android Service全解(二)之 bindService(转)
    android单点、多点触控之MotionEvent
    关于创建进程函数CreateProcess()字符串参数的说明
    sql中连接两个不同的数据库(A在同一个服务器,B不在一个服务器)
    asp.net小数点四舍五入的方法
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6257174.html
Copyright © 2020-2023  润新知