码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ 2738】 矩阵乘法

时间:2015-05-12 09:23:52      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:bzoj   oi   思路题   整体二分   

2738: 矩阵乘法

Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 841 Solved: 351
[Submit][Status][Discuss]
Description

  给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
Input

  第一行两个数N,Q,表示矩阵大小和询问组数;
  接下来N行N列一共N*N个数,表示这个矩阵;
  再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
Output

  对于每组询问输出第K小的数。
Sample Input

2 2

2 1

3 4

1 2 1 2 1

1 1 2 2 3

Sample Output

1

3

HINT

  矩阵中数字是109以内的非负整数;

  20%的数据:N<=100,Q<=1000;

  40%的数据:N<=300,Q<=10000;

  60%的数据:N<=400,Q<=30000;

  100%的数据:N<=500,Q<=60000。


思路题+整体二分。

首先把矩阵中的元素升序排序,然后就可以整体二分了。

即二分每个询问矩阵是在第几大的元素加的时候达到了k个(用二维树状数组优化)。

【BZOJ 2527】一样了。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define M 500005
using namespace std;
struct jz
{
    int x,y,v;
}a[M];
struct Query
{
    int x1,y1,x2,y2,k,id,cur;
}q[M],b[M];
int t[505][505],ans[M],n,Q;
bool cmp(jz a,jz b)
{
    return a.v<b.v;
}
int lowbit(int x)
{
    return x&(-x);
}
void Update(int x,int y,int k)
{
    if (!x) x++;
    if (!y) y++;
    for (int i=x;i<=n;i+=lowbit(i))
        for (int j=y;j<=n;j+=lowbit(j))
            t[i][j]+=k;
}
int sum(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+=t[i][j];
    return ans;
}
int Getsum(int x)
{
    return sum(b[x].x2,b[x].y2)-sum(b[x].x2,b[x].y1-1)-sum(b[x].x1-1,b[x].y2)+sum(b[x].x1-1,b[x].y1-1); 
}
void read(int &tmp)
{
    tmp=0;
    char ch=getchar();
    int fu=1;
    for (;ch<‘0‘||ch>‘9‘;ch=getchar())
        if (ch==‘-‘) fu=-1;
    for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar())
        tmp=tmp*10+ch-‘0‘;
    tmp*=fu;
}
void Solve(int l,int r,int h,int t)
{
    if (h>t) return;
    if (l==r)
    {
        for (int i=h;i<=t;i++)
            ans[b[i].id]=a[l].v;
        return;
    }
    int mid=(l+r)>>1;
    for (int i=l;i<=mid;i++)
        Update(a[i].x,a[i].y,1);
    int t1=h-1,t2=t+1;
    for (int i=h;i<=t;i++)
    {
        int tmp=Getsum(i);
        if (tmp+b[i].cur>=b[i].k) q[++t1]=b[i];
        else b[i].cur+=tmp,q[--t2]=b[i];
    }
    for (int i=h;i<=t;i++)
        b[i]=q[i];
    for (int i=l;i<=mid;i++)
        Update(a[i].x,a[i].y,-1);
    Solve(l,mid,h,t1);
    Solve(mid+1,r,t2,t);
}
int main()
{
    scanf("%d%d",&n,&Q);
    int now=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            read(a[++now].v),a[now].x=i,a[now].y=j;
    sort(a+1,a+1+now,cmp);
    for (int i=1;i<=Q;i++)
        read(b[i].x1),read(b[i].y1),read(b[i].x2),read(b[i].y2),read(b[i].k),
        b[i].id=i,b[i].cur=0;
    Solve(1,now,1,Q);
    for (int i=1;i<=Q;i++)
        printf("%d\n",ans[i]);
    return 0;
}

技术分享

【BZOJ 2738】 矩阵乘法

标签:bzoj   oi   思路题   整体二分   

原文地址:http://blog.csdn.net/regina8023/article/details/45664415

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!