【BZOJ 2738】 矩阵乘法|分块|离线

好像还有其他的高大上的算法

不过分块最简单了

直接分成n块 暴力搞就行

详见popoQQQ http://blog.csdn.net/popoqqq/article/details/41356899


卡过去的 跑的好慢

错过几次

1.范围500不是200

2.最后输出q个 不是n个

3.中间有变量写错


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=60000+10;
bool b[MAXN];
int x1[MAXN],x2[MAXN],y1[MAXN],y2[MAXN],qk[MAXN];
struct H
{
	int x,y;
	int v;
}num[500*500+10];
int sum[510][510],cnt[510][510];
int n,q;
bool cmp(H a,H b)
{
	return a.v<b.v;
}
int ans[MAXN];
int main()
{
	cin>>n>>q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			int x,tmp=i*n-n+j;
			scanf("%d",&x);
			num[tmp].x=i;
			num[tmp].y=j;
			num[tmp].v=x;
		}
	sort(num+1,num+n*n+1,cmp);
	for(int i=1;i<=q;i++) scanf("%d %d %d %d %d",&x1[i],&y1[i],&x2[i],&y2[i],&qk[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=i*n-n+1;j<=i*n;j++)
		{
			cnt[num[j].x][num[j].y]=1;//cout<<num[j].x<<" "<<num
		}
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				sum[j][k]=sum[j][k-1]+sum[j-1][k]-sum[j-1][k-1]+cnt[j][k];//cout<<sum[n][n]<<endl;
		for(int j=1;j<=q;j++)
		{
			if(b[j]) continue;
			int su=sum[x2[j]][y2[j]]-sum[x2[j]][y1[j]-1]-sum[x1[j]-1][y2[j]]+sum[x1[j]-1][y1[j]-1];//cout<<i<<' '<<j<<' '<<sum[n][n]<<endl;
			if(su<qk[j]) continue;
			int k=su-qk[j];//cout<<'*'<<k<<endl;
			int w=i*n;
			for(;k;w--)
				if(num[w].x<=x2[j]&&num[w].x>=x1[j]&&num[w].y<=y2[j]&&num[w].y>=y1[j])
					k--;
			for(;true;w--)
				if(num[w].x<=x2[j]&&num[w].x>=x1[j]&&num[w].y<=y2[j]&&num[w].y>=y1[j])
				{
					ans[j]=num[w].v;
					break;
				}
			b[j]=true;	
		}
	}
	for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值