Tsinsen A1333. 矩阵乘法(梁 盾)

智商康复计划。。。。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a));
using namespace std;
const int N=500+5;
const int Q=60000+5;
const int inf=1e9;
struct Query{
	int x1,y1,x2,y2,k,cur,id;
}q[Q],q1[Q],q2[Q];
struct Num{
	int x,y,z;
}a[N*N],a1[N*N],a2[N*N];
int d[N][N],n;
int lb(int x){return x&-x;}
void add(int x,int y,int z){
	for(int i=x;i<=n;i+=lb(i))
	for(int j=y;j<=n;j+=lb(j))
	d[i][j]+=z;
}
int sum(int x,int y){
	int ans=0;
	for(int i=x;i>0;i-=lb(i))
	for(int j=y;j>0;j-=lb(j))
	ans+=d[i][j];
	return ans;
}
int sum(int x1,int y1,int x2,int y2){
	return sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1);
}
int ans[Q];
void divide(int h,int t,int l,int r,int al,int ar){
	if(h>t)return;
	if(al==ar){
		rep(i,h,t)ans[q[i].id]=al;
		return;
	}
	int mid=al+ar>>1;
	int l1=0,l2=0,t1=0,t2=0;
	rep(i,l,r)
	if(a[i].z<=mid)add(a[i].x,a[i].y,1),a1[++t1]=a[i];
	else a2[++t2]=a[i];
	rep(i,h,t){
		int tmp=sum(q[i].x1,q[i].y1,q[i].x2,q[i].y2);
		if(q[i].cur+tmp>=q[i].k)q1[++l1]=q[i];
		else q[i].cur+=tmp,q2[++l2]=q[i];
	}
	rep(i,1,t1)a[l+i-1]=a1[i],add(a1[i].x,a1[i].y,-1);
	rep(i,1,t2)a[l+t1+i-1]=a2[i];
	rep(i,1,l1)q[h+i-1]=q1[i];
	rep(i,1,l2)q[h+l1+i-1]=q2[i];
	divide(h,h+l1-1,l,l+t1-1,al,mid);
	divide(h+l1,t,l+t1,r,mid+1,ar);
}
int main(){
	//freopen("a.in","r",stdin);
	int m;scanf("%d%d",&n,&m);
	rep(i,1,n)rep(j,1,n)
	scanf("%d",&a[(i-1)*n+j].z),a[(i-1)*n+j].x=i,a[(i-1)*n+j].y=j;
	rep(i,1,m)scanf("%d%d%d%d%d",&q[i].x1,&q[i].y1,&q[i].x2,&q[i].y2,&q[i].k),q[i].id=i;
	divide(1,m,1,n*n,0,inf);
	rep(i,1,m)printf("%d\n",ans[i]);
	return 0;
}


你可能感兴趣的:(Tsinsen A1333. 矩阵乘法(梁 盾))