zoukankan      html  css  js  c++  java
  • [BZOJ2738]矩阵乘法(整体二分+二维树状数组)

    整体二分+二维树状数组。

    好题啊!写了一个来小时。

    一看这道题,主席树不会搞,只能用离线的做法了。

    整体二分真是个好东西,啥都可以搞,尤其是区间第 (k) 大这种东西。

    我们二分答案,然后用二维树状数组实现 (log^2 n) 的单点修改,时间复杂度 (O(qlog^2 nlog 10^9))

    (Code Below:)

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-(x)))
    #define id(x,y) (((x)-1)*n+(y)) 
    using namespace std;
    const int maxn=300000+10;
    const int lim=1e9;
    int n,m,c[510][510],ans[maxn];
     
    struct Element{
        int x,y,k;
    }e[maxn],e1[maxn],e2[maxn];
     
    bool cmp(Element a,Element b){
        return a.k<b.k;
    }
     
    struct Query{
        int x1,y1,x2,y2,k,id;
    }q[maxn],q1[maxn],q2[maxn];
     
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
     
    inline void add(int x,int y,int z){
        for(int i=x;i<=n;i+=lowbit(i))
            for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=z;
    }
     
    inline int sum(int x,int y){
        int ans=0;
        for(int i=x;i;i-=lowbit(i))
            for(int j=y;j;j-=lowbit(j)) ans+=c[i][j];
        return ans;
    }
     
    void solve(int L,int R,int Le,int Ri,int l,int r){
        if(L>R||Le>Ri) return ;
        if(l==r){
            for(int i=Le;i<=Ri;i++) ans[q[i].id]=l;
            return ;
        }
        int mid=(l+r)>>1,cnt1=0,cnt2=0,tot1=0,tot2=0,val;
        for(int i=L;i<=R;i++){
            if(e[i].k<=mid) add(e[i].x,e[i].y,1),e1[++cnt1]=e[i];
            else e2[++cnt2]=e[i];
        }
        for(int i=1;i<=cnt1;i++) e[L+i-1]=e1[i];
        for(int i=1;i<=cnt2;i++) e[L+i+cnt1-1]=e2[i];
        for(int i=Le;i<=Ri;i++){
            val=sum(q[i].x2,q[i].y2)-sum(q[i].x1-1,q[i].y2)-sum(q[i].x2,q[i].y1-1)+sum(q[i].x1-1,q[i].y1-1);
            if(val>=q[i].k) q1[++tot1]=q[i];
            else q[i].k-=val,q2[++tot2]=q[i];
        }
        for(int i=L;i<=L+cnt1-1;i++) add(e[i].x,e[i].y,-1);
        for(int i=1;i<=tot1;i++) q[Le+i-1]=q1[i];
        for(int i=1;i<=tot2;i++) q[Le+i+tot1-1]=q2[i];
        solve(L,L+cnt1-1,Le,Le+tot1-1,l,mid);
        solve(L+cnt1,R,Le+tot1,Ri,mid+1,r);
    }
     
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) e[id(i,j)].x=i,e[id(i,j)].y=j,e[id(i,j)].k=read();
        sort(e+1,e+n*n+1,cmp);
        for(int i=1;i<=m;i++) q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read(),q[i].k=read(),q[i].id=i;
        solve(1,n*n,1,m,0,lim);
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    三、linux系统管理
    二、基本命令
    一、基本环境
    mysql-day4
    mysql-day3
    mysql-day2
    mysql-day1
    3、线性表的链式存储结构
    2、线性表之顺序表
    1、时间复杂度
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10198104.html
Copyright © 2011-2022 走看看