zoukankan      html  css  js  c++  java
  • 【BZOJ2738】矩阵乘法 [整体二分][树状数组]

    矩阵乘法

    Time Limit: 20 Sec  Memory Limit: 256 MB
    [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

      矩阵中数字是10^9以内的非负整数;
      20%的数据:N<=100,Q<=1000;
      40%的数据:N<=300,Q<=10000;
      60%的数据:N<=400,Q<=30000;
      100%的数据:N<=500,Q<=60000。

    Solution

      由于只有询问,我们可以方便地使用整体二分来求解。

      先将原矩阵以序列形式存下来,然后按照权值排序,接着我们二分序列上的位置来查询,在[l,mid]这一段序列上的点+1,然后像静态查Kth那么判断即可。(用二维树状数组加入权值)。

    Code

      1 #include<iostream>  
      2 #include<string>  
      3 #include<algorithm>  
      4 #include<cstdio>  
      5 #include<cstring>  
      6 #include<cstdlib>  
      7 #include<cmath>  
      8 #include<vector>
      9 using namespace std;  
     10 
     11 const int ONE = 505;
     12 const int QUE = 60005;
     13 
     14 int n,Q;
     15 int tot;
     16 int C[ONE][ONE];
     17 int Ans[QUE]; 
     18 
     19 struct point
     20 {
     21         int x,y,val;
     22 }a[ONE*ONE];
     23 bool cmp(const point &a,const point &b) {return a.val < b.val;}
     24 
     25 struct power
     26 {
     27         int x1,y1,x2,y2;
     28         int k;
     29         int id;
     30 }oper[QUE],qL[QUE],qR[QUE];
     31 
     32 int get() 
     33 {
     34         int res=1,Q=1;  char c;
     35         while( (c=getchar())<48 || c>57)
     36         if(c=='-')Q=-1;
     37         if(Q) res=c-48; 
     38         while((c=getchar())>=48 && c<=57) 
     39         res=res*10+c-48; 
     40         return res*Q; 
     41 }
     42 
     43 namespace Bit
     44 {
     45         int lowbit(int x) {return x&-x;}
     46         
     47         void Add(int x,int y,int z)
     48         {
     49             for(int i=x;i<=n;i+=lowbit(i))
     50                 for(int j=y;j<=n;j+=lowbit(j))
     51                     C[i][j] += z;
     52         }
     53         
     54         int Query(int x,int y)
     55         {
     56             int res = 0;
     57             for(int i=x;i>=1;i-=lowbit(i))
     58                 for(int j=y;j>=1;j-=lowbit(j))
     59                     res += C[i][j];
     60             return res;
     61         }
     62         
     63         int Getans(power a)
     64         {
     65             return Query(a.x2,a.y2) - Query(a.x1-1,a.y2) - Query(a.x2,a.y1-1) + Query(a.x1-1,a.y1-1);
     66         }
     67 }
     68 
     69 void Solve(int l,int r,int L,int R)//位置 询问 
     70 {
     71         if(L>R) return;
     72         if(l==r)
     73         {
     74             for(int i=L;i<=R;i++)
     75                 Ans[oper[i].id] = a[l].val;
     76             return;
     77         }
     78         
     79         int mid=(l+r)>>1;
     80         for(int i=l;i<=mid;i++)
     81             Bit::Add(a[i].x,a[i].y,1);
     82         
     83         int l_num=0,r_num=0;
     84         for(int i=L;i<=R;i++)
     85         {
     86             int record = Bit::Getans(oper[i]); 
     87             if(record >= oper[i].k)
     88                 qL[++l_num] = oper[i];
     89             else
     90                 oper[i].k-=record, qR[++r_num] = oper[i];
     91         }
     92         
     93         for(int i=l;i<=mid;i++)
     94             Bit::Add(a[i].x,a[i].y,-1);
     95         
     96         int t=L;
     97         for(int i=1;i<=l_num;i++) oper[t++] = qL[i];
     98         for(int i=1;i<=r_num;i++) oper[t++] = qR[i];
     99         
    100         Solve(l,mid,L,L+l_num-1);
    101         Solve(mid+1,r,L+l_num,R);
    102 }
    103 
    104 
    105 int main()
    106 {
    107         n=get();    Q=get();
    108         for(int i=1;i<=n;i++)
    109         for(int j=1;j<=n;j++)
    110         {
    111             a[++tot].val = get();
    112             a[tot].x = i;    a[tot].y = j;
    113         }
    114         sort(a+1,a+tot+1,cmp);
    115         
    116         for(int i=1;i<=Q;i++)
    117         {
    118             oper[i].x1=get();    oper[i].y1=get();    oper[i].x2=get();    oper[i].y2=get();
    119             oper[i].k=get();    oper[i].id=i;
    120         }
    121         
    122         Solve(1,tot,1,Q);
    123         
    124         for(int i=1;i<=Q;i++)
    125             printf("%d
    ",Ans[i]);
    126 }
    View Code
  • 相关阅读:
    机器学习中常见的优化算法
    linux端安装Anaconda,方便远端访问jupyter
    核心③自动分号插入
    setTimeout 和 setInterval
    核心②undefined 和 null
    类型④类型转换
    核心①为什么不要使用 eval
    类型③instanceof 操作符
    类型①相等与比较
    类型②typeof 操作符
  • 原文地址:https://www.cnblogs.com/BearChild/p/6561673.html
Copyright © 2011-2022 走看看