洛谷 P1527 [国家集训队]矩阵乘法 解题报告

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

题目描述

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

输入输出格式

输入格式:

第一行两个数\(N,Q\),表示矩阵大小和询问组数;

接下来\(N\)\(N\)列一共\(N*N\)个数,表示这个矩阵;

再接下来\(Q\)行每行\(5\)个数描述一个询问:\(x1,y1,x2,y2,k\)表示找到以\((x1,y1)\)为左上角、以\((x2,y2)\)为右下角的子矩形中的第\(K\)小数。

输出格式:

对于每组询问输出第\(K\)小的数。

说明

矩阵中数字是\(10^9\)以内的非负整数;

\(20\%\)的数据:\(N<=100,Q<=1000\)

\(40\%\)的数据:\(N<=300,Q<=10000\)

\(60\%\)的数据:\(N<=400,Q<=30000\)

\(100\%\)的数据:\(N<=500,Q<=60000\)


整体二分真有趣。

直接把整体二分里面的改成二维树状数组就可以了

复杂度\(O((N^2+M)\log10^9\log N^2)\)


Code:

#include <cstdio>
const int N=502;
const int M=310010;
const int inf=0x3f3f3f3f;
struct node{int op,a,b,c,d,k;}q[M],ql[M],qr[M];
int s[N][N],n,m,Q,ans[M];
void add(int x,int y,int d)
{
    for(int i=x;i<=n;i+=i&-i)
        for(int j=y;j<=n;j+=j&-j)
            s[i][j]+=d;
}
int query(int x,int y)
{
    int sum=0;
    for(int i=x;i;i-=i&-i)
        for(int j=y;j;j-=j&-j)
            sum+=s[i][j];
    return sum;
}
#define rep(i,a,b) for(int i=a;i<=b;i++)
void divide(int l,int r,int s,int t)
{
    if(s>t)return;
    if(l==r){rep(i,s,t)ans[q[i].op]=l;return;}
    int mid=l+r>>1,lp=0,rp=0;
    rep(i,s,t)
    {
        if(q[i].op)
        {
            int p=query(q[i].c,q[i].d)-query(q[i].c,q[i].b-1)
                 -query(q[i].a-1,q[i].d)+query(q[i].a-1,q[i].b-1);
            if(q[i].k<=p) ql[++lp]=q[i];
            else qr[++rp]=q[i],qr[rp].k-=p;
        }
        else
        {
            if(q[i].k<=mid) add(q[i].a,q[i].b,1),ql[++lp]=q[i];
            else qr[++rp]=q[i];
        }
    }
    rep(i,s,t) if(!q[i].op&&q[i].k<=mid) add(q[i].a,q[i].b,-1);
    rep(i,s,s+lp-1) q[i]=ql[i+1-s];
    rep(i,s+lp,t) q[i]=qr[i+1-s-lp];
    divide(l,mid,s,s+lp-1),divide(mid+1,r,s+lp,t);
}
int main()
{
    scanf("%d%d",&n,&Q);
    rep(i,1,n) rep(j,1,n) ++m,scanf("%d",&q[m].k),q[m].a=i,q[m].b=j;
    rep(i,1,Q) ++m,scanf("%d%d%d%d%d",&q[m].a,&q[m].b,&q[m].c,&q[m].d,&q[m].k),q[m].op=i;
    divide(0,inf,1,m);
    rep(i,1,Q) printf("%d\n",ans[i]);
    return 0;
}

2018.11.1

posted @ 2018-11-01 22:06  露迭月  阅读(249)  评论(0编辑  收藏  举报