zoukankan      html  css  js  c++  java
  • BZOJ 2738: 矩阵乘法 [整体二分]

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

    愚蠢的名字......
    整体二分,影响因子就是矩阵里的数
    把$le mid$的矩阵元素加到二维树状数组里然后询问分成两组就行了
    可以把矩阵元素权值排序后直接二分矩阵元素而不是值
    复杂度$O(nlog^3n)$
    用排序代替一维树状数组理论上更快,但需要把矩阵里的元素和查询放到一个数组里再排序貌似常数太大
    然后发现黄学长的做法是错误的复杂度不对....但竟然比我快....
     
    二维树状数组一定不要写错!!!
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=505,M=6e4+5,INF=1e9;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,Q;
    struct Factor{
        int x,y,v;
        Factor(){}
        Factor(int a,int b,int c):x(a),y(b),v(c){}
        bool operator <(const Factor &r)const{return v<r.v;}
    }a[N*N];
    int m,now=0;
    
    struct Query{
        int x1,y1,x2,y2,k;
    }q[M];
    int id[M],t1[M],t2[M],cur[M];
    
    int c[N][N];
    inline int lowbit(int x){return x&-x;}
    inline void add(int x,int y,int v){
        for(int i=x;i<=n;i+=lowbit(i))
            for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=v;
    }
    inline int sum(int x,int y){
        int re=0;
        for(int i=x;i;i-=lowbit(i))
            for(int j=y;j;j-=lowbit(j)) re+=c[i][j];
        return re;
    }
    inline int que(int i){
        int x1=q[i].x1-1,y1=q[i].y1-1,x2=q[i].x2,y2=q[i].y2;
        return sum(x2,y2)-sum(x1,y2)-sum(x2,y1)+sum(x1,y1);
    }
    int ans[M];
    void Sol(int l,int r,int ql,int qr){
        if(ql>qr) return;
        if(l==r){
            for(int i=ql;i<=qr;i++) ans[id[i]]=a[l].v;
            return;
        }
        int mid=(l+r)>>1;
        for(int i=l;i<=mid;i++) add(a[i].x,a[i].y,1);
        int p1=0,p2=0;
        for(int i=ql;i<=qr;i++){
            int u=id[i],s=cur[u]+que(u);
            if(s>=q[u].k) t1[++p1]=u;
            else t2[++p2]=u,cur[u]=s;
        }
        for(int i=l;i<=mid;i++) add(a[i].x,a[i].y,-1);
        for(int i=1;i<=p1;i++) id[ql+i-1]=t1[i];
        for(int i=1;i<=p2;i++) id[ql+p1+i-1]=t2[i];
        Sol(l,mid,ql,ql+p1-1);
        Sol(mid+1,r,ql+p1,qr);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();Q=read();
        for(int i=1;i<=n;i++) 
            for(int j=1;j<=n;j++) a[++m]=Factor(i,j,read());
        for(int i=1;i<=Q;i++) 
            q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read(),q[i].k=read();
        sort(a+1,a+1+m);
        for(int i=1;i<=Q;i++) id[i]=i;
        Sol(1,m,1,Q);
        for(int i=1;i<=Q;i++) printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    今天再次认真整理了浏览器收藏夹
    今天再次认真整理了浏览器收藏夹
    【博客之星】CSDN2013博客之星--分析和预测
    【博客之星】CSDN2013博客之星--分析和预测
    CSDN博客的文章分类和战略规划
    CSDN博客的文章分类和战略规划
    《社交红利》读书总结--如何从微信微博QQ空间等社交网络带走海量用户、流量与收入
    《社交红利》读书总结--如何从微信微博QQ空间等社交网络带走海量用户、流量与收入
    个人名片与诚信
    个人名片与诚信
  • 原文地址:https://www.cnblogs.com/candy99/p/6445734.html
Copyright © 2011-2022 走看看