zoukankan      html  css  js  c++  java
  • Luogu1527[国家集训队]矩阵乘法

    Luogu1527[国家集训队]矩阵乘法

    题面:洛谷

    解析

    排名第(k)大,不妨考虑整体二分,二分第(k)大的数值(mid),,将大于(mid)的值视作1,添加到树状数组中,对每一个询问,判断它的询问区域中1的点的个数是否大于询问排名,即可将询问分作两部分递归,然而这样的复杂度是(O(n^{2}log{n})),我们不妨将二分值域变为二分数值在矩阵中对应的排名,再先将矩阵中的数排序,就不用每一次都遍历整个矩阵找到大于(mid)的数了。

    代码

    
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<algorithm>
    #define N 505
    #define M 60005
    using namespace std;
    int n,m,id[M],ans[M],t1[M],t2[M],tc;
    struct Q{ int x1,y1,x2,y2,k; }q[M];
    struct Mat{
        int v,x,y;
        bool operator < (const Mat& rhs) const { return v<rhs.v; }
    }mat[N*N];
    int a[N][N];
    inline int In(){
        char c=getchar(); int x=0,ft=1;
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
        for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
        return x*ft;
    }
    inline int LB(int x){
        return x&(-x);
    }
    inline void Add(int x,int y,int C){
        for(int i=x;i<=n;i+=LB(i))
        for(int j=y;j<=n;j+=LB(j))
        a[i][j]+=C;
    }
    inline int Sum(int x,int y){
        int s=0;
        for(int i=x;i;i-=LB(i))
        for(int j=y;j;j-=LB(j))
        s+=a[i][j];
        return s;
    }
    inline int Query(int x1,int y1,int x2,int y2){
        return Sum(x2,y2)-Sum(x1-1,y2)-Sum(x2,y1-1)+Sum(x1-1,y1-1);
    }
    void Solve(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]]=l;
            return;
        }
        int mid=(l+r)>>1,p1=0,p2=0;
        for(int i=l;i<=mid;++i) Add(mat[i].x,mat[i].y,1);
        for(int i=ql,u,s;i<=qr;++i){
            u=id[i]; s=Query(q[u].x1,q[u].y1,q[u].x2,q[u].y2);
            if(s>=q[u].k) t1[++p1]=u;
            else q[u].k-=s,t2[++p2]=u;
        }
        for(int i=l;i<=mid;++i) Add(mat[i].x,mat[i].y,-1);
        for(int i=ql;i<=ql+p1-1;++i) id[i]=t1[i-ql+1];
        for(int i=ql+p1;i<=qr;++i) id[i]=t2[i-ql-p1+1];
        Solve(l,mid,ql,ql+p1-1); Solve(mid+1,r,ql+p1,qr);
    }
    int main(){
        n=In(); m=In();
        for(int i=1;i<=n;++i) for(int j=1;j<=n;++j)
        mat[++tc].v=In(),mat[tc].x=i,mat[tc].y=j;
        sort(mat+1,mat+1+tc);
        for(int i=1;i<=m;++i){
            q[i].x1=In(); q[i].y1=In();
            q[i].x2=In(); q[i].y2=In();
            q[i].k=In(); id[i]=i;
        }
        Solve(1,n*n,1,m);
        for(int i=1;i<=m;++i) printf("%d
    ",mat[ans[i]].v);
        return 0;
    }
    
    
  • 相关阅读:
    Nokia Lumia 800销售反馈 苹果iPhone、三星Galaxy不敌800设计
    各大网站用户数据库被爆,遭大量网友下载
    最美发明家:GPS、手机通讯网都源自她的发明
    iPhone5或明年下半年发布 配备iOS6和A6芯片
    保存文件到手机内存
    2012年十大科技趋势:NFC、语音控制与弯曲屏
    电脑报独家报道:宽带升级全国真相调查
    Android的电话拨号器
    Java程序员成长之路(接口与抽象类究竟有什么区别)
    联系人相关
  • 原文地址:https://www.cnblogs.com/pkh68/p/10526726.html
Copyright © 2011-2022 走看看