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

Posted 租酥雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu1527][国家集训队]矩阵乘法相关的知识,希望对你有一定的参考价值。

luogu

题意

给你一个\(N*N\)的矩阵,每次询问一个子矩形的第K小数。(居然连修改都不带的)
\(N\le500,Q\le60000\)

sol

整体二分+二维树状数组裸题。
复杂度是\(O((n^2+Q)\log n^2 \log^2 n)\)也就是\(3\)\(\log\)吧。

code

#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 4e5+5;
struct node{int id,x1,y1,x2,y2,k;}q[N],q1[N],q2[N];
int n,m,cnt,o[N],len,c[505][505],ans[N];
void modify(int x,int y,int v)
{
    for (int i=x;i<=n;i+=i&-i)
        for (int j=y;j<=n;j+=j&-j)
            c[i][j]+=v;
}
int query(int x,int y)
{
    int res=0;
    for (int i=x;i;i-=i&-i)
        for (int j=y;j;j-=j&-j)
            res+=c[i][j];
    return res;
}
void solve(int L,int R,int l,int r)
{
    if (L>R) return;
    if (l==r)
    {
        for (int i=L;i<=R;++i) ans[q[i].id]=l;
        return;
    }
    int mid=l+r>>1,t1=0,t2=0;
    for (int i=L;i<=R;++i)
        if (!q[i].id)
        {
            if (q[i].k<=mid) modify(q[i].x1,q[i].y1,1),q1[++t1]=q[i];
            else q2[++t2]=q[i];
        }
        else
        {
            int tmp=query(q[i].x2,q[i].y2)-query(q[i].x1-1,q[i].y2)-query(q[i].x2,q[i].y1-1)+query(q[i].x1-1,q[i].y1-1);
            if (q[i].k<=tmp) q1[++t1]=q[i];
            else q[i].k-=tmp,q2[++t2]=q[i];
        }
    for (int i=L;i<=R;++i)
        if (!q[i].id&&q[i].k<=mid) modify(q[i].x1,q[i].y1,-1);
    for (int i=L,j=1;j<=t1;++i,++j) q[i]=q1[j];
    for (int i=L+t1,j=1;j<=t2;++i,++j) q[i]=q2[j];
    solve(L,L+t1-1,l,mid);solve(L+t1,R,mid+1,r);
}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n;++j)
            q[++cnt]=(node){0,i,j,0,0,o[++len]=gi()};
    sort(o+1,o+len+1);len=unique(o+1,o+len+1)-o-1;
    for (int i=1;i<=cnt;++i)
        q[i].k=lower_bound(o+1,o+len+1,q[i].k)-o;
    for (int i=1;i<=m;++i)
        q[++cnt]=(node){i,gi(),gi(),gi(),gi(),gi()};
    solve(1,cnt,1,len);
    for (int i=1;i<=m;++i) printf("%d\n",o[ans[i]]);
    return 0;
}

以上是关于[Luogu1527][国家集训队]矩阵乘法的主要内容,如果未能解决你的问题,请参考以下文章

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

luogu_P2044题解 随机数生成器 矩阵乘法

LUOGU P4159 [SCOI2009]迷路(矩阵乘法)

矩阵乘法入门

向MapReduce转换:通过部分成绩计算矩阵乘法

[luogu4159 SCOI2009] 迷路(矩阵乘法)