zoukankan      html  css  js  c++  java
  • BZOJ2738 矩阵乘法

    题目

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

    思路

    整体二分。

    整体二分主要适用于对于二分状态的改变,可以在可接受的复杂度内修改的题目。

    就本题而言,二分答案,如果考虑将[1,mid]的区间内的点加入树状数组中,在二维平面上标记为1,然后比较每个询问与K的关系,接着将询问分组,接着二分。

    以上应该是整体二分的基本模型。

    代码

    #include<bits/stdc++.h>
    #define M 60005
    using namespace std;
    struct node{
        int x,y,val;
        bool operator < (const node& res)const{
            return val<res.val;
        }
    }B[505*505];
    int n,Q,A[505][505],bcnt,ans[M],t1[M],t2[M];
    int id[M],now;
    struct que{
        int x1,y1,x2,y2,k;
    }wk[M];
    struct BIT{
        int C[505][505];
        void Add(int x,int y,int d){
            x++;y++;
            while(x<=n+1){
                int a=y;
                while(y<=n+1){
                    C[x][y]+=d;
                    y+=(y&-y);
                }   
                y=a;
                x+=(x&-x);
            }
        }
        int sum(int x,int y){
            x++;y++;
            int res=0;
            while(x){
                int a=y;
                while(y){
                    res+=C[x][y];
                    y-=(y&-y);
                }
                y=a;
                x-=(x&-x);
            }
            return res;
        }
    }T;
    void update(int x,int f){
        T.Add(B[x].x,B[x].y,f); 
    }
    int query(int x1,int y1,int x2,int y2){
        return T.sum(x2,y2)-T.sum(x1-1,y2)-T.sum(x2,y1-1)+T.sum(x1-1,y1-1); 
    }
    void solve(int l,int r,int ql,int qr){
        if(l>r)return;
        if(ql==qr){
            for(int i=l;i<=r;i++)ans[id[i]]=ql;
            return;
        }
        int mid=(ql+qr)>>1,c1=0,c2=0,c=l-1;
        while(now<mid)update(++now,1);
        while(now>mid)update(now--,-1);
        for(int i=l;i<=r;i++){
            if(query(wk[id[i]].x1,wk[id[i]].y1,wk[id[i]].x2,wk[id[i]].y2)<wk[id[i]].k)t1[++c1]=id[i];
            else t2[++c2]=id[i];
        }
        for(int i=1;i<=c2;i++)id[++c]=t2[i];
        for(int i=1;i<=c1;i++)id[++c]=t1[i];
        solve(l,l+c2-1,ql,mid);solve(l+c2,r,mid+1,qr);
    }
    int main(){
    //  freopen("1.in","r",stdin);
    //  freopen("1.ans","w",stdout);
        scanf("%d%d",&n,&Q);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&A[i][j]),B[++bcnt].val=A[i][j],B[bcnt].x=i,B[bcnt].y=j;
        sort(B+1,B+bcnt+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                int l=1,r=bcnt,res=-1;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(B[mid].val>=A[i][j]){
                        res=mid;
                        r=mid-1;
                    }
                    else l=mid+1;
                }
                A[i][j]=res;
            }
        for(int i=1;i<=Q;i++){
            scanf("%d%d%d%d%d",&wk[i].x1,&wk[i].y1,&wk[i].x2,&wk[i].y2,&wk[i].k);
            id[i]=i;
        }
        solve(1,Q,1,bcnt);
        for(int i=1;i<=Q;i++){
            printf("%d
    ",B[ans[i]].val);
        }
        return 0;
    }
    
  • 相关阅读:
    第四篇 -- 收获颇丰的一天
    第十六篇 -- SuperIO学习
    第八篇 -- 用U盘制作启动盘装Win10系统
    第二十五篇 -- 学习第三十四天打卡20190726
    zabbix钉钉报警
    windows 远程连接“发生身份验证错误 要求的函数不受支持”
    限制IP远程访问
    查看、踢出在线用户
    codis
    Linux、windows安装java
  • 原文地址:https://www.cnblogs.com/zryabc/p/11232030.html
Copyright © 2011-2022 走看看