query

  题目描述:T组数据,对于每组数据,n个数ai,Q个询问(L,R,h),询问L到R区间内≤h的数的个数

  数据范围:30%     n,Q≤10^3

                    100%   T≤10  n,Q≤10^5 1≤L≤R≤n 0≤ai,h≤10^9

  暴力枚举肯定是能过30%的点

  对于100%的点,有一种离线做法是按照a,h把数组和询问分别排序,再用树状数组,比较容易想到,看代码能懂

 const maxn=100005;
 var id,id1,a,h,left,right,c,ans:array[0..maxn]of longint;
     test,t,i,j,n,Q,k:longint;
 procedure swap(var x,y:longint);
  var t:longint;
   begin
    t:=x;x:=y;y:=t;
   end;
 procedure qsort(L,R:longint);
  var i,j,mid:longint;
   begin
    i:=L;j:=R;mid:=a[random(R-L+1)+L];
    repeat
     while a[i]<mid do inc(i);
     while a[j]>mid do dec(j);
      if i<=j then begin
                    swap(a[i],a[j]);swap(id[i],id[j]);
                    inc(i);dec(j);
                   end;
    until i>j;
    if i<R then qsort(i,R);
    if L<j then qsort(L,j);
   end;
 procedure qsort1(L,R:longint);
  var i,j,mid:longint;
   begin
    i:=L;j:=R;mid:=h[random(R-L+1)+L];
    repeat
     while h[i]<mid do inc(i);
     while h[j]>mid do dec(j);
      if i<=j then begin
                    swap(h[i],h[j]);swap(left[i],left[j]);swap(right[i],right[j]);swap(id1[i],id1[j]);
                    inc(i);dec(j);
                   end;
    until i>j;
    if i<R then qsort1(i,R);
    if L<j then qsort1(L,j);
   end;
 function lowbit(x:longint):longint;
  begin
   lowbit:=x and (-x);
  end;
 procedure add(x,y:longint);
  begin
   while x<=n do
    begin
     inc(c[x],y);
     inc(x,lowbit(x));
    end;
  end;
 function get(x:longint):longint;
  var s:longint;
   begin
    s:=0;
    while x>=1 do
     begin
      inc(s,c[x]);
      dec(x,lowbit(x));
     end;
    exit(s);
   end;
 begin
  assign(input,'query.in');reset(input);
  assign(output,'query.out');rewrite(output);
  readln(test);
  for t:=1 to test do
   begin
    fillchar(c,sizeof(c),0);
    readln(n,Q);
    for i:=1 to n do
     begin
      id[i]:=i;
      read(a[i]);
     end;
    readln;
    for i:=1 to Q do
     begin
      id1[i]:=i;
      readln(left[i],right[i],h[i]);
     end;
    qsort(1,n);
    qsort1(1,Q);
    i:=1;j:=1;
    while j<=Q do
     begin
      if (i>n)or(h[j]<a[i]) then begin
                                  ans[id1[j]]:=get(right[j])-get(left[j]-1);
                                  inc(j);
                                 end
                            else begin
                                  add(id[i],1);
                                  inc(i);
                                 end;
     end;
   for i:=1 to Q do writeln(ans[i]);
   end;
   close(input);close(output);
  end.

根据度老师给出的题解,还有在线做法:暴力主席树/树套树/kd-tree,此处不贴代码#因为没去写过,对于离线做法,还可以对位置排序,不过必须离线,大致意思差不多,但是会麻烦一点。

【写的有漏洞的,欢迎路过大神吐槽】

  2016/11/13 17:05:33

  Ending.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值