BZOJ2738 矩阵乘法(梁 盾) 整体二分

本文介绍了一种结合整体二分法与二维树状数组的数据处理方法,该方法适用于解决特定类型的问题,尽管其复杂度为Q*log(Q)^3,在某些情况下不如分块方法高效(Q*sqrt(Q))。通过具体的C++代码实现展示了如何进行区间更新和查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    这道题还是整体二分。。  在二维树状数组外面套一个二分

    但对于这道题来说,整体二分的复杂度是 Q*log(Q)^3 不如分块优(Q*sqrt(Q))

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <functional>
#define INF 1000000000
#define MAXN 350000
#define lowbit(x) ((x)&(-(x)))
using namespace std;
struct node
{
    int x1,y1,x2,y2,s,k,cur,tp;
}q[MAXN],q1[MAXN],q2[MAXN];
int tmp[MAXN],ans[MAXN];
int c[600][600];
int n,m,tot;
void modify(const int &x,const int &y,const int &d)
{
    for (int i=x;i<=n;i+=lowbit(i))
        for (int j=y;j<=n;j+=lowbit(j))
            c[i][j]+=d;
}
int query(const int &x,const int &y)
{
    int res=0;
    for (int i=x;i>0;i-=lowbit(i))
        for (int j=y;j>0;j-=lowbit(j))
            res+=c[i][j];
    return res;
}
void solve(int head,int tail,int L,int R)
{
    if (head>tail) return;
    if (L==R)
    {
        for (int i=head;i<=tail;++i)
            if (q[i].tp==2) ans[q[i].s]=L;
        return;
    }
    int mid=(L+R)/2;
    for (int i=head;i<=tail;++i)
    {
        if (q[i].tp==1&&q[i].k<=mid) modify(q[i].x1,q[i].y1,1);
        else if (q[i].tp==2) tmp[i]=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);
    }
    for (int i=head;i<=tail;++i)
        if (q[i].tp==1&&q[i].k<=mid) modify(q[i].x1,q[i].y1,-1);
    int l1=0,l2=0;
    for (int i=head;i<=tail;++i)
    {
        if (q[i].tp==2)
        {
            if (q[i].cur+tmp[i]>q[i].k-1)
                q1[++l1]=q[i];
            else
            {
                q[i].cur+=tmp[i];
                q2[++l2]=q[i];
            }
        }
        else
        {
            if (q[i].k<=mid) q1[++l1]=q[i];
            else q2[++l2]=q[i];
        }
    }
    for (int i=1;i<=l1;++i) q[head+i-1]=q1[i];
    for (int i=1;i<=l2;++i) q[head+l1+i-1]=q2[i];
    solve(head,head+l1-1,L,mid);
    solve(head+l1,tail,mid+1,R);
}
int getint()
{
    char c;
    int res=0;
    while (isspace(c=getchar())) ;
    res=c-48;
    while (isdigit(c=getchar())) res=res*10+c-48;
    return res;
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n;++j)
        {
            int x;
            x=getint();
            q[++tot].x1=i;q[tot].y1=j;
            q[tot].k=x;q[tot].tp=1;
        }
    for (int i=1;i<=m;++i)
    {
        ++tot;
        q[tot].x1=getint(),q[tot].y1=getint(),q[tot].x2=getint(),q[tot].y2=getint(),q[tot].k=getint();
        q[tot].tp=2; q[tot].s=i;
    }
    solve(1,tot,0,INF);
    for (int i=1;i<=m;++i)
        printf("%d\n",ans[i]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值