• [BZOJ2738]矩阵乘法 整体二分+二维树状数组


    2738: 矩阵乘法

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 1643  Solved: 715
    [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。

    先将矩阵中所有元素排序,然后对于所有询问一起二分

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 int n,q;
     9 struct tmp {
    10     int v,x,y;
    11     bool operator <(const tmp &t)const {
    12         return v<t.v;
    13     }
    14 }a[250005];
    15 int cnt=0;
    16 struct data {
    17     int x1,y1,x2,y2,k,id,ans;
    18 }ask[60006],s[60005];
    19 int sum[505][505];
    20 int lowbit(int x){return x&(-x);}
    21 void update(int x,int y,int add) {
    22     for(int i=x;i<=n;i+=lowbit(i))
    23         for(int j=y;j<=n;j+=lowbit(j)) sum[i][j]+=add;
    24 }
    25 int query(int x,int y) {
    26     int an=0;
    27     for(int i=x;i>0;i-=lowbit(i))
    28         for(int j=y;j>0;j-=lowbit(j)) an+=sum[i][j];
    29     return an;
    30 }
    31 int get(int x1,int y1,int x2,int y2) {
    32     return query(x2,y2)+query(x1-1,y1-1)-query(x1-1,y2)-query(x2,y1-1);
    33 }
    34 void solve(int l,int r,int ql,int qr) {
    35     if(ql>qr) return;
    36     if(l==r) {
    37         for(int i=ql;i<=qr;i++) ask[i].ans=a[l].v;
    38         return ;
    39     }
    40     int mid=(l+r)>>1;
    41     for(int i=l;i<=mid;i++) update(a[i].x,a[i].y,1);
    42     int head=ql-1,tail=0;
    43     for(int i=ql;i<=qr;i++) {
    44         int nowk=get(ask[i].x1,ask[i].y1,ask[i].x2,ask[i].y2);
    45         if(nowk>=ask[i].k) ask[++head]=ask[i];
    46         else {s[++tail]=ask[i];s[tail].k-=nowk;}
    47     }
    48     for(int i=1;i<=tail;i++) ask[++head]=s[i];
    49     for(int i=l;i<=mid;i++) update(a[i].x,a[i].y,-1);
    50     solve(l,mid,ql,qr-tail);
    51     solve(mid+1,r,qr-tail+1,qr);
    52     return ;
    53 }
    54 bool cmp(data t1,data t2) {
    55     return t1.id<t2.id;
    56 }
    57 int main() {
    58     scanf("%d%d",&n,&q);
    59     for(int i=1;i<=n;i++)
    60         for(int j=1;j<=n;j++){scanf("%d",&a[++cnt].v);a[cnt].x=i;a[cnt].y=j;}
    61     sort(a+1,a+cnt+1);
    62     for(int i=1;i<=q;i++) {
    63         scanf("%d%d%d%d%d",&ask[i].x1,&ask[i].y1,&ask[i].x2,&ask[i].y2,&ask[i].k);
    64         ask[i].id=i;
    65     }
    66     solve(1,cnt,1,q);
    67     sort(ask+1,ask+1+q,cmp);
    68     for(int i=1;i<=q;i++) printf("%d
    ",ask[i].ans);
    69 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    X-CTF(REVERSE入门) python-trade
    X-CTF(REVERSE入门) getit
    X-CTF(REVERSE入门) csaw2013reversing2
    X-CTF(REVERSE入门) no-strings-attached
    X-CTF(REVERSE入门) insanity
    X-CTF(REVERSE入门) logmein
    面向对象编程的七大设计原则
    二叉树的性质
    Visual Studio 2017 WPF应用(.Net Freamwork)断点调试不命中的解决方法
    C语言读写文件
  • 原文地址:https://www.cnblogs.com/wls001/p/7728681.html
Copyright © 2020-2023  润新知