P1527 [国家集训队]矩阵乘法 (整体二分)

这里我选择了一种在线的树状数组的写法,有三个log,比较好写但是跑的比较慢,吸氧才能过

其实和一维的没有区别,都是整体二分值域的思想

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
int tr[510][510];
struct node{
    int op,x,y,x2,y2,k,id;
}q[N],lq[N],rq[N];
int ans[N];
int a[510][510];
int lowbit(int x){
    return x&-x;
}
void add(int x,int y,int c){
    int i,j;
    for(i=x;i<=510;i+=lowbit(i)){
        for(j=y;j<=510;j+=lowbit(j)){
            tr[i][j]+=c;
        }
    }
}
int sum(int x,int y){
    int i,j;
    int ans=0;
    for(i=x;i;i-=lowbit(i)){
        for(j=y;j;j-=lowbit(j)){
            ans+=tr[i][j];
        }
    }
    return ans;
}
void solve(int vl,int vr,int ql,int qr){
    if(ql>qr){
        return ;
    }
    int i;
    int n1=0;
    int n2=0;
    if(vl==vr){
        for(i=ql;i<=qr;i++){
            if(q[i].op==2)
                ans[q[i].id]=vl;
        }
        return ;
    }
    int mid=vl+vr>>1;
    for(i=ql;i<=qr;i++){
        if(q[i].op==1){
            if(q[i].x2<=mid)
                add(q[i].x,q[i].y,1),lq[++n1]=q[i];
            else
                rq[++n2]=q[i];

        }
        else{
            int n=sum(q[i].x2,q[i].y2)+sum(q[i].x-1,q[i].y-1)-sum(q[i].x2,q[i].y-1)-sum(q[i].x-1,q[i].y2);
            if(n>=q[i].k){
                lq[++n1]=q[i];
            }
            else{
                q[i].k-=n;
                rq[++n2]=q[i];
            }
        }
    }
    for(i=ql;i<=qr;i++){
        if(q[i].op==1){
            if(q[i].x2<=mid)
                add(q[i].x,q[i].y,-1);
        }
    }
    for(i=1;i<=n1;i++)
        q[ql+i-1]=lq[i];
    for(i=1;i<=n2;i++)
        q[ql+n1+i-1]=rq[i];
    solve(vl,mid,ql,ql+n1-1);
    solve(mid+1,vr,ql+n1,qr);
}
int main(){
    int n,q1;
    cin>>n>>q1;
    int i,j;
    int cnt=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            cin>>a[i][j];
            q[++cnt]=node{1,i,j,a[i][j]};
        }
    }
    for(i=1;i<=q1;i++){
        int x,y,x2,y2,k;
        scanf("%d%d%d%d%d",&x,&y,&x2,&y2,&k);
        q[++cnt]=node{2,x,y,x2,y2,k,i};
    }
    solve(0,1e9,1,cnt);
    for(i=1;i<=q1;i++){
        printf("%d\n",ans[i]);
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12805176.html