BZOJ2738 矩陣乘法(梁 盾) 整體二分

    這道題還是整體二分。。  在二維樹狀數組外面套一個二分

    但對於這道題來說,整體二分的複雜度是 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]);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章