Sequence by 唐迪(不是splay)

(原标题有误,写成spaly)

传说是某道国家集训队作业题。

但是,做法相当朴素,只不过是离线回答的。

事实再次证明,离线在大多数情况下优于在线,其原因在于可以充分利用已经算出的答案进行调整。

problem:

题目一

 

题目描述:

因为小t喜欢吃糖,所以他经常在桌子上摆上一排彩色的糖。每种糖都用一种特殊的颜色标识,而每种颜色我们用数字1、2、3、……表示。现在小t在桌子上摆了n颗糖果。现在小t有困惑了,他想知道从第L颗糖果到第R颗糖果中共有多少种不同的糖果。

YourTask:

帮助小t,完成每一个询问

 

输入文件:

第一行两个数n、m

第二行n个数ai,表示第i颗糖的颜色

接下来m行每行两个数L、R

 

输出文件:

m行,对应输入的每一个询问的答案

 

样例输入:

5 1

1 2 3 4 5

1 5

 

样例输出:

5

 

数据约定:

ai <= 10^6

m <= 10^5

n <= 5*10^4

1 <= L <= R <= n

solution:将所有询问读入,以左端点为一关键字,以右端点为二关键字排序,每次根据新增的区间或减少的区间修改答案,y[i]>r是保证右端点递增,方便编程。

另,罗雨屏说,这题或许可用曼哈顿生成树。

再另,时隔多日,罗雨屏再说,利用GSS2的离线思想,预处理找出每个数字的下一个位置,将每个数字第一次出现的位置标为一,原问题转化为在一段区间内统计1的个数(线段树)。

当扫过一个数字,则将该数字下一个位置零改为一。完虐标程裸做。于是这道题我得再写一遍。

var n,m,l,r,tot,i:longint;
    d,a:array[0..50000]of longint;
    ans,x,y,z:array[1..100000]of longint;
    c:array[1..100000]of boolean;
procedure qsort(l,r:longint);
var i,j,x1,y1,c:longint;
begin
 i:=l;j:=r;x1:=x[(l+r)>>1];y1:=y[(l+r)>>1];
 repeat
  while (x[i]<x1)or((x[i]=x1)and(y[i]<y1)) do inc(i);
  while (x1<x[j])or((x1=x[j])and(y1<y[j])) do dec(j);
  if not(i>j) then begin
   c:=x[i];x[i]:=x[j];x[j]:=c;
   c:=y[i];y[i]:=y[j];y[j]:=c;
   c:=z[i];z[i]:=z[j];z[j]:=c;
   inc(i);dec(j)
  end
 until i>j;
 if i<r then qsort(i,r);
 if l<j then qsort(l,j)
end;
procedure work(x,y:longint);
//var i:longint;
begin
 for i:=l to x-1 do begin
  dec(d[a[i]]);
  if d[a[i]]=0 then dec(tot)
 end;
 for i:=r+1 to y do begin
  inc(d[a[i]]);
  if d[a[i]]=1 then inc(tot)
 end;
 l:=x;r:=y
end;
procedure doit;
var i:longint;
    check:boolean;
begin
 check:=true;
 fillchar(c,sizeof(c),true);
 while check do begin
  check:=false;
  l:=1;r:=0;tot:=0;
  fillchar(d,sizeof(d),0);
  for i:=1 to m do
   if (c[i])and(y[i]>r) then begin
    work(x[i],y[i]);ans[z[i]]:=tot;c[i]:=false;
    check:=true
   end
 end;
end;
procedure init;
var i,xx,j:longint;
begin
 readln(n,m);
 for i:=1 to n do read(a[i]);
 for i:=1 to m do begin readln(x[i],y[i]);z[i]:=i end;
 qsort(1,m);
 doit;
 for i:=1 to m do writeln(ans[i])
end;
begin
assign(input,'sequence.in');reset(input);
assign(output,'sequence.out');rewrite(output);
 init;
close(input);close(output)
end.

新发,线段树版,速度超快

uses math;
var n,mm,m1,m:longint;
    d:array[1..131072]of longint;
    l,r,q,ans,p,a:array[1..100000]of longint;
    v:array[0..1000000]of longint;
procedure inf;
begin
 assign(input,'sequence.in');reset(input);
 assign(output,'sequence.out');rewrite(output)
end;
procedure ouf;
begin
 close(input);close(output)
end;
procedure qsort(ll,rr:longint);
var i,j,x,c:longint;
begin
 i:=ll;j:=rr;x:=l[(ll+rr)>>1];
 repeat
  while l[i]<x do inc(i);
  while x<l[j] do dec(j);
  if not(i>j) then begin
   c:=l[i];l[i]:=l[j];l[j]:=c;
   c:=r[i];r[i]:=r[j];r[j]:=c;
   c:=q[i];q[i]:=q[j];q[j]:=c;
   inc(i);dec(j)
  end
 until i>j;
 if i<rr then qsort(i,rr);
 if ll<j then qsort(ll,j)
end;
procedure origin;
begin
 m1:=1;
 while m1<=mm+2 do m1:=m1<<1;m1:=m1+1
end;
procedure change(x,w:longint);
begin
 if x=0 then exit;
 d[x+m1]:=w;x:=(x+m1)>>1;
 while x<>0 do begin
   inc(d[x],w);
   x:=x>>1
 end
end;
function ask(l,r:longint):longint;
begin
 l:=l+m1-1;r:=r+m1+1;ask:=0;
 while not(l xor r=1) do begin
   if l and 1=0 then ask:=ask+d[l+1];
   if r and 1=1 then ask:=ask+d[r-1];
   l:=l>>1;r:=r>>1
 end
end;
procedure init;
var i,j:longint;
begin
 readln(n,m);
 for i:=1 to n do read(a[i]);readln;
 fillchar(v,sizeof(v),0);
 mm:=0;
 for i:=n downto 1 do begin
   p[i]:=v[a[i]];
   v[a[i]]:=i;
   mm:=max(mm,a[i])
 end;
 origin;
 for i:=0 to mm do
  if v[i]<>0 then change(v[i],1);
 for i:=1 to m do begin
   readln(l[i],r[i]);
   q[i]:=i
 end;
 qsort(1,m);
 j:=1;
 for i:=1 to n do begin
  while l[j]=i do begin
    ans[q[j]]:=ask(l[j],r[j]);
    inc(j)
  end;
  change(p[i],1)
 end;
 for i:=1 to m do writeln(ans[i])
end;
begin
  inf;
  init;
  ouf
end.
     


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值