• 洛谷 P1527 [国家集训队]矩阵乘法


    矩阵第k小

    一道练习整体二分的比较好的题

    这道题把序列查询区间第(k)小搬到了矩阵上,但是仍然满足二分性质,所以我们还是可以整体二分

    而我们沿用序列上的做法,把点和询问都离线下来,揉在一起整体二分

    唯一不一样的地方就是需要二维树状数组,这个很好理解吧qwq

    复杂度(O(Qlog^3n))

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    const int N = 500;
    const int M = 6e4;
    const int N2 = 250000;
    const int INF = 1e9;
    using namespace std;
    struct node
    {
        int x1,y1,x2,y2,k,id;
    }q[M + N2 + 5],q1[M + N2 + 5],q2[M + N2 + 5];
    int n,m,a[N + 5][N + 5],ans[M + 5],c[N + 5][N + 5],cnt;
    int lowbit(int x)
    {
        return x & (-x);
    }
    void add(int x,int y,int s)
    {
        for (int i = x;i <= n;i += lowbit(i))
            for (int j = y;j <= n;j += lowbit(j))
                c[i][j] += s;
    }
    int query(int x,int y)
    {
        if (!x || !y)
            return 0;
        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;
    }
    int query_sum(int x1,int y1,int x2,int y2)
    {
        return query(x2,y2) - query(x1 - 1,y2) - query(x2,y1 - 1) + query(x1 - 1,y1 - 1);
    }
    void solve(int l,int r,int L,int R)
    {
        if (L > R)
            return;
        if (l == r)
        {
            for (int i = L;i <= R;i++)
                if (q[i].id)
                    ans[q[i].id] = l;
            return;
        }
        int mid = l + r >> 1,cnt1 = 0,cnt2 = 0;
        for (int i = L;i <= R;i++)
            if (q[i].id == 0)
            {
                if (q[i].k <= mid)
                {
                    add(q[i].x1,q[i].y1,1);
                    q1[++cnt1] = q[i];
                }
                else
                    q2[++cnt2] = q[i];
            }
            else
            {
                int x = query_sum(q[i].x1,q[i].y1,q[i].x2,q[i].y2);
                if (x >= q[i].k)
                    q1[++cnt1] = q[i];
                else
                {
                    q[i].k -= x;
                    q2[++cnt2] = q[i];
                }
            }
        for (int i = 1;i <= cnt1;i++)
            if (q1[i].id == 0)
                add(q1[i].x1,q1[i].y1,-1);
        for (int i = L;i <= L + cnt1 - 1;i++)
            q[i] = q1[i - L + 1];
        for (int i = L + cnt1;i <= R;i++)
            q[i] = q2[i - L - cnt1 + 1];
        solve(l,mid,L,L + cnt1 - 1);
        solve(mid + 1,r,L + cnt1,R);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i = 1;i <= n;i++)
            for (int j = 1;j <= n;j++)
            {
                scanf("%d",&a[i][j]);
                q[++cnt] = (node){i,j,0,0,a[i][j],0};
            }
        for (int i = 1;i <= m;i++)
        {
            cnt++;
            scanf("%d%d%d%d%d",&q[cnt].x1,&q[cnt].y1,&q[cnt].x2,&q[cnt].y2,&q[cnt].k);
            q[cnt].id = i;
        }
        solve(0,INF,1,cnt);
        for (int i = 1;i <= m;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    程序员必看书籍(转载)
    JBPM的ORACLE脚本
    XFire构建web service客户端的五种方式
    为什么中国出不了facebook和Twitter?
    用dwr封装表单项提交表单
    Java 程序员容易犯的10个SQL错误
    SQL语句优化方法30例
    sqlserver sql语句查看分区记录数、查看记录所在分区
    SQL Case when 的使用方法
    sqlserver sql语句附加 分离数据库
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068063.html
Copyright © 2020-2023  润新知