• bzoj2738: 矩阵乘法


    2738: 矩阵乘法

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 1396  Solved: 603
    [Submit][Status][Discuss]

    Description

      给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。

    Input

     
      第一行两个数N,Q,表示矩阵大小和询问组数;
      接下来N行N列一共N*N个数,表示这个矩阵;
      再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。

    Output

      对于每组询问输出第K小的数。

    Sample Input

    2 2
    2 1
    3 4
    1 2 1 2 1
    1 1 2 2 3

    Sample Output

    1
    3

    HINT

      矩阵中数字是109以内的非负整数;

      20%的数据:N<=100,Q<=1000;

      40%的数据:N<=300,Q<=10000;

      60%的数据:N<=400,Q<=30000;

      100%的数据:N<=500,Q<=60000。

    题解

    整体二分,把正常区间k大的做法中的一维树状数组和二维树状数组就行了。

    我把数组开大十倍……就不T了……感觉奥妙重重啊

      1 program j01;
      2 type xx=record x1,y1,x2,y2,k,id:longint; end;
      3      yy=record x,y,w:longint; end;
      4 var c:array[0..600,0..600]of longint;
      5     op,tmp:array[0..600086]of xx;
      6     ans:array[0..600086]of longint;
      7     a:array[0..3000000]of yy;
      8     tt,n,m,i,j:longint;
      9 
     10 procedure qsort(l,r:longint);
     11 var i,j,x:longint;y:yy;
     12 begin
     13   i:=l;j:=r;x:=a[i].w;
     14   repeat
     15     while a[i].w<x do inc(i);
     16     while x<a[j].w do dec(j);
     17     if i<=j then
     18     begin
     19       y:=a[i];a[i]:=a[j];a[j]:=y;
     20       inc(i);dec(j);
     21     end;
     22   until i>j;
     23   if i<r then qsort(i,r);
     24   if l<j then qsort(l,j);
     25 end;
     26 
     27 procedure add(x,y,dd:longint);
     28 var i,j:longint;
     29 begin
     30   i:=x;
     31   while i<=n do
     32   begin
     33     j:=y;
     34     while j<=n do
     35     begin
     36       inc(c[i,j],dd);j:=j+(j and(-j));
     37     end;
     38     i:=i+(i and(-i));
     39   end;
     40 end;
     41 
     42 function ask(x,y:longint):longint;
     43 var i,j:longint;
     44 begin
     45   ask:=0;i:=x;
     46   while i>0 do
     47   begin
     48     j:=y;
     49     while j>0 do
     50     begin
     51       inc(ask,c[i,j]);j:=j-(j and(-j));
     52     end;
     53     i:=i-(i and(-i));
     54   end;
     55 end;
     56 
     57 procedure solve(ql,qr,l,r:longint);
     58 var i,tmpp,lt,rt,mid:longint;
     59 begin
     60   if ql>qr then exit;
     61   if l=r then
     62   begin
     63     for i:=ql to qr do ans[op[i].id]:=a[l].w;
     64     exit;
     65   end;
     66   lt:=ql-1;rt:=qr+1;mid:=(l+r)div 2;
     67   for i:=l to mid do
     68     add(a[i].x,a[i].y,1);
     69   for i:=ql to qr do
     70   begin
     71     tmpp:=ask(op[i].x2,op[i].y2)-ask(op[i].x2,op[i].y1-1)-ask(op[i].x1-1,op[i].y2)+ask(op[i].x1-1,op[i].y1-1);
     72     if tmpp>=op[i].k then
     73     begin
     74       inc(lt);tmp[lt]:=op[i];
     75     end else
     76     begin
     77       op[i].k:=op[i].k-tmpp;
     78       dec(rt);tmp[rt]:=op[i];
     79     end;
     80   end;
     81   for i:=l to mid do
     82     add(a[i].x,a[i].y,-1);
     83   for i:=ql to qr do op[i]:=tmp[i];
     84   solve(ql,lt,l,mid);
     85   solve(rt,qr,mid+1,r);
     86 end;
     87 
     88 begin
     89   readln(n,m);
     90   tt:=0;
     91   for i:=1 to n do
     92     for j:=1 to n do
     93     begin
     94       inc(tt);a[tt].x:=i;a[tt].y:=j;
     95       read(a[tt].w);
     96     end;
     97   qsort(1,tt);
     98   for i:=1 to m do
     99   begin
    100     read(op[i].x1,op[i].y1,op[i].x2,op[i].y2,op[i].k);
    101     op[i].id:=i;
    102   end;
    103   solve(1,m,1,tt);
    104   for i:=1 to m do writeln(ans[i]);
    105 end.
    View Code
  • 相关阅读:
    Oracle冷备份需要保存的文件
    oracle 重建 sys密码文件
    ORA-01991错误
    oracle ORA-01033问题怎么解决
    oracle创建表空间
    oracle 10G服务器端安装以及冷备份恢复
    完全卸载oracle11g步骤
    42. 函数指针用在菜单驱动系统中,练习函数指针数组的使用。
    41. 定义与调用一个函数指针时的几种方式
    40. 使用数组时的四个要点
  • 原文地址:https://www.cnblogs.com/oldjang/p/6404283.html
Copyright © 2020-2023  润新知