• [国家集训队]矩阵乘法 整体二分


    很好的一道题,令人大开眼界。

    Code:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 1000000
    #define N 600
    using namespace std;
    int n,Q,idx,q[maxn],tl[maxn],tr[maxn],answer[maxn],cur[maxn]; 
    struct MAT{
        int x,y,w; 
    }mat[maxn]; 
    int cmp(MAT a,MAT b){ return a.w<b.w;}
    struct Query{
        int a,b,c,d,k; 
    }ask[maxn];
    struct BIT{
        int C[N][N];
        int lowbit(int x){ return x&(-x);}
        void add(int x,int y,int k)
        {
            for(int i=x;i<=n;i+=lowbit(i))
                for(int j=y;j<=n;j+=lowbit(j)) C[i][j]+=k;
        }
        int query(int x,int y)
        {
            int ans=0;
            for(int i=x;i>0;i-=lowbit(i))
                for(int j=y;j>0;j-=lowbit(j)) ans+=C[i][j];
            return ans; 
        }
        int ask(Query a)
        {
            return query(a.c,a.d)-query(a.c,a.b-1)-query(a.a-1,a.d)+query(a.a-1,a.b-1); 
        }
    }tree;
    void solve(int x,int y,int l,int r){
        if(x>y||l>r) return;
        if(l==r){
            for(int i=x;i<=y;++i) answer[q[i]]=mat[l].w;
            return; 
        }
        int mid=(l+r)>>1;
        for(int i=l;i<=mid;++i) tree.add(mat[i].x,mat[i].y,1);
        int left=0,right=0,s,u;
        for(int i=x;i<=y;++i){
            u=q[i];
            s=cur[u]+tree.ask(ask[u]);  
            if(s>=ask[u].k) tl[++left]=u;
            else tr[++right]=u,cur[u]=s; 
        }
        int qcnt=x-1;
        for(int i=1;i<=left;++i) q[++qcnt]=tl[i];
        for(int i=1;i<=right;++i) q[++qcnt]=tr[i];
        for(int i=l;i<=mid;++i) tree.add(mat[i].x,mat[i].y,-1);
        solve(x,x+left-1,l,mid),solve(x+left,y,mid+1,r);
    }
    int main(){
        //setIO("input"); 
        scanf("%d%d",&n,&Q);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j){
                mat[++idx].x=i,mat[idx].y=j;
                scanf("%d",&mat[idx].w); 
            }
        sort(mat+1,mat+1+idx,cmp);
        for(int i=1;i<=Q;++i) 
            scanf("%d%d%d%d%d",&ask[i].a,&ask[i].b,&ask[i].c,&ask[i].d,&ask[i].k),q[i]=i; 
        solve(1,Q,1,idx); 
        for(int i=1;i<=Q;++i) printf("%d
    ",answer[i]);
        return 0; 
    }
    

      

  • 相关阅读:
    数学考试
    奇♂妙拆分
    11.25
    11.21
    11.20
    11.19
    11.18
    11.15
    11.14作业
    11.14
  • 原文地址:https://www.cnblogs.com/guangheli/p/10262509.html
Copyright © 2020-2023  润新知