您的位置:首页 > 其它

BZOJ 2738: 矩阵乘法 整体二分 二维树状数组

2017-08-21 11:17 519 查看

2738: 矩阵乘法

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 1579  Solved: 681

[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。

整体二分 二维树状数组

做上一道题时每太想明白整体二分过程中状态转移的复杂度

好好YY一下就可以发现是树状数组复杂度*线性复杂度,还是很棒的

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef long long ll;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)x=-x,putchar('-');if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=510,M=60100,inf=0X3f3f3f3f;

struct P{int val,x,y;friend bool operator <(const P &x,const P &y){return x.val<y.val;}}a[N*N];

struct question{int x1,y1,x2,y2,k;}qu[M];

int bit

;

int n,now,fan[M];

inline void bitmodify(int x,int y,int val)
{
if(!x||!y)return ;
register int i;
for(;x<=n;x+=(x&-x))for(i=y;i<=n;i+=(i&-i))
bit[x][i]+=val;
}

inline int query(int x,int y)
{
if(!x||!y)return 0;
register int i,res=0;
for(;x;x-=(x&-x))for(i=y;i;i-=(i&-i))res+=bit[x][i];
return res;
}

inline bool check(int x)
{
int res=query(qu[x].x2,qu[x].y2);
res+=query(qu[x].x1-1,qu[x].y1-1);
res-=query(qu[x].x1-1,qu[x].y2);res-=query(qu[x].x2,qu[x].y1-1);
return res>=qu[x].k;
}

int tmp1[M],tmp2[M],ans[M];

void solve(int x,int y,int l,int r)
{
register int i,mid,cnt1=0,cnt2=0;
if(x>y||l==r){for(i=x;i<=y;++i)ans[fan[i]]=l;return ;}
mid=(l+r)>>1;
while(a[now+1].val<=mid&&now<n*n)now++,bitmodify(a[now].x,a[now].y,1);
while(a[now].val>mid&&now)bitmodify(a[now].x,a[now].y,-1),now--;
for(i=x;i<=y;++i)
{check(fan[i])?tmp1[++cnt1]=fan[i]:tmp2[++cnt2]=fan[i];}
for(i=x;i<x+cnt1;++i)fan[i]=tmp1[i-x+1];
for(i=x+cnt1;i<=y;++i)fan[i]=tmp2[i-cnt1-x+1];
solve(x,x+cnt1-1,l,mid);solve(x+cnt1,y,mid+1,r);
}

int main()
{
n=read();int Q=read();
register int i,j;
for(i=1;i<=n;++i)for(j=1;j<=n;++j){a[(i-1)*n+j]=(P){read(),i,j};}
sort(a+1,a+1+n*n);
for(i=1;i<=Q;++i){qu[i]=(question){read(),read(),read(),read(),read()};fan[i]=i;}
solve(1,Q,1,inf);
for(i=1;i<=Q;++i)print(ans[i]),puts("");
return 0;
}
/*
2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3

1
3
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: