• BZOJ_2738_矩阵乘法_整体二分


    BZOJ_2738_矩阵乘法_整体二分

    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。


     可以离线,把权值排序。

    solve(b,e,l,r)表示b到e的询问的答案在l到r范围的权值内。

    答案mid,就插入前mid个数,然后查询区间有多少个数,可以用二维树状数组维护。

    答案在左边就往左走,在右边就减去左边的贡献往右走。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 60050
    int n,c[550][550],L[N],R[N],mid[N],ans[N];
    struct A {
        int v,x,y;
    }a[550*550];
    struct Q {
        int d,f,g,h,k,id;
    }q[N],t[N];
    bool cmp(const A &a,const A &b) {
        return a.v<b.v;
    }
    void fix(int x,int y,int v) {
        int i,j;
        for(i=x;i<=n;i+=i&(-i)) {
            for(j=y;j<=n;j+=j&(-j)) {
                c[i][j]+=v;
            }
        }
    }
    int inq(int x,int y) {
        int i,j,re=0;
        for(i=x;i;i-=i&(-i)) {
            for(j=y;j;j-=j&(-j)) {
                re+=c[i][j];
            }
        }
        return re;
    }
    int query(int x,int y,int x2,int y2) {
        x--; y--;
        return inq(x2,y2)-inq(x,y2)-inq(x2,y)+inq(x,y);
    }
    void solve(int b,int e,int l,int r) {
        int i;
        if(b>e) return ;
        if(l==r) {
            for(i=b;i<=e;i++) {
                ans[q[i].id]=a[l].v;
            }
            return ;
        }
        int mid=(l+r)>>1,lpos=b,rpos=e;
        for(i=l;i<=mid;i++) {
            fix(a[i].x,a[i].y,1);
        }
        for(i=b;i<=e;i++) {
            int sizls=query(q[i].d,q[i].f,q[i].g,q[i].h);
            if(sizls>=q[i].k) t[lpos++]=q[i];
            else q[i].k-=sizls,t[rpos--]=q[i];
        }
        for(i=b;i<=e;i++) q[i]=t[i];
        for(i=l;i<=mid;i++) {
            fix(a[i].x,a[i].y,-1);
        }
        solve(b,lpos-1,l,mid);
        solve(rpos+1,e,mid+1,r);
    }
    int main() {
        int m;
        scanf("%d%d",&n,&m);
        int i,tot=0,j;  
        for(i=1;i<=n;i++) {
            for(j=1;j<=n;j++) {
                scanf("%d",&a[++tot].v);
                a[tot].x=i; a[tot].y=j;
            }
        }
        sort(a+1,a+n*n+1,cmp);
        for(i=1;i<=m;i++) {
            scanf("%d%d%d%d%d",&q[i].d,&q[i].f,&q[i].g,&q[i].h,&q[i].k);
            q[i].id=i;
        }
        solve(1,m,1,n*n);
        for(i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    十八、分页查询
    十七、oracle的权限和角色
    十六、同义词(synonyms)
    十五、序列
    十四、禁用与启动约束
    十三、修改表时添加约束
    十二、约束
    十一、修改表格
    十、事务(Transaction)
    Windows 远程连接后,自动断开,所有程序都自动关闭(待验证,待更新)
  • 原文地址:https://www.cnblogs.com/suika/p/8967222.html
Copyright © 2020-2023  润新知