国家集训队 矩阵乘法

题目描述

题解:

考虑到答案具有单调性,我们将其放入二维树状数组/二维线段树即可。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 505
#define Q 60050
#define ll long long
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,ans[Q],mx,lp[N*N],rp[N*N],to[N*N];
struct node
{
    int x,y,k;
}p[N*N];
struct sqr
{
    int x_,y_,_x,_y,k,id;
    void read()
    {
        x_ = rd(),y_ = rd(),_x = rd(),_y = rd(),k = rd();
    }
}q[Q],tmpl[Q],tmpr[Q];
bool cmp(node a,node b)
{
    return a.k<b.k;
}
struct BIT
{
    ll f[N][N];
    void up(int x,int y,ll d)
    {
        if(!x||!y)return ;
        for(int i=x;i<N;i+=(i&-i))
            for(int j=y;j<N;j+=(j&-j))
                f[i][j]+=d;
    }
    ll down(int x,int y)
    {
        if(!x||!y)return 0;
        ll ret = 0;
        for(int i=x;i;i-=(i&-i))
            for(int j=y;j;j-=(j&-j))
                ret+=f[i][j];
        return ret;
    }
}tr;
void update(int k,int d)
{
    for(int i=lp[k];i<=rp[k];i++)
        tr.up(p[i].x,p[i].y,d);
}
ll ask(int x_,int y_,int _x,int _y)
{
    return tr.down(_x,_y)+tr.down(x_-1,y_-1)-tr.down(_x,y_-1)-tr.down(x_-1,_y);
}
int tim;
void divi(int l,int r,int beg,int ens)
{
    if(beg>ens)return ;
    if(l==r)
    {
        for(int i=beg;i<=ens;i++)
            ans[q[i].id] = to[l];
        return ;
    }
    int mid = (l+r)>>1;
    while(tim<mid)tim++,update(tim,1);
    while(tim>mid)update(tim,-1),tim--;
    int lt = 0,rt = 0;
    for(int i=beg;i<=ens;i++)
    {
        ll sum = ask(q[i].x_,q[i].y_,q[i]._x,q[i]._y);
        if(sum>=q[i].k)tmpl[++lt] = q[i];
        else tmpr[++rt] = q[i];
    }
    for(int i=beg;i<=beg+lt-1;i++)q[i]=tmpl[i-beg+1];
    for(int i=beg+lt;i<=ens;i++)q[i]=tmpr[i-beg-lt+1];
    divi(l,mid,beg,beg+lt-1);
    divi(mid+1,r,beg+lt,ens);
}
int main()
{
    n = rd(),m = rd();
    for(int i=1;i<=n*n;i++)
    {
        p[i].x = (i-1)/n+1;
        p[i].y = (i-1)%n+1;
        p[i].k = rd();
    }
    sort(p+1,p+1+n*n,cmp);
    for(int las=-1,i=1;i<=n*n;i++)
    {
        if(p[i].k!=las)
        {
            rp[mx] = i-1;
            las = p[i].k;
            mx++;
            lp[mx] = i;
            to[mx] = las;
        }
        p[i].k = mx;
    }
    rp[mx] = n*n;
    for(int i=1;i<=m;i++)
        q[i].read(),q[i].id=i;
    divi(1,mx+1,1,m);
    for(int i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10201409.html