bzoj1926: [Sdoi2010]粟粟的书架

AC:100题

这是一道2合一水题。。。

看数据范围:

对于 50%的数据,满足 R, C≤200,M≤200,000 

另有 50%的数据,满足 R=1,C≤500,000,M≤20,000

所以对于50%的数据用a[i][j][k]表示比k大的数的个数,b[i][j][k]表示比k大的数的和。O(1000*RC)预处理+O(log 1000)询问水过。

另50%的数据考虑主席树,v[i]表示i节点对应区间个数,s[i]表示区间和,O(C log 1000)预处理+O(log 1000)询问。

lych大说他可能有一种通用方法,然而空间不够?

卡着空间过了。。。//把a[i][j][k]变成a[k][i][j]后居然会变慢!无法理解。。。

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,T,a[210][210][1010],b[210][210][1010],c[210][210],x1,y1,x2,y2,h;
int t,rt[550000],ls[11000000],rs[11000000],v[11000000],s[11000000],cnt;
int read()
{
	char c=getchar();int x=0;
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x;
}
void work1()
{
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
		c[i][j]=read();
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
	for (int k=1;k<=1000;k++)
	{
		a[i][j][k]=a[i][j-1][k]+a[i-1][j][k]-a[i-1][j-1][k];
		b[i][j][k]=b[i][j-1][k]+b[i-1][j][k]-b[i-1][j-1][k];
		if (c[i][j]>=k) a[i][j][k]++,b[i][j][k]+=c[i][j];
	}
	while (T--)
	{
		x1=read(),y1=read(),x2=read(),y2=read(),h=read();
		int L=0,R=1001;x1--;y1--;
		while (L+1<R)
		{
			int mid=(L+R)>>1;
			if (b[x1][y1][mid]+b[x2][y2][mid]-b[x2][y1][mid]-b[x1][y2][mid]>=h) L=mid; else R=mid;
		}
		if (L==0) puts("Poor QLW");
		else
		{
			int sum1=b[x1][y1][L]+b[x2][y2][L]-b[x2][y1][L]-b[x1][y2][L]-h;
			int sum2=a[x1][y1][L]+a[x2][y2][L]-a[x2][y1][L]-a[x1][y2][L];
			printf("%d\n",sum2-sum1/L);
		}
	}
}
void add(int l,int r,int x,int &y,int k)
{
	y=++cnt;v[y]=v[x]+1;s[y]=s[x]+k;
	if (l==r) return;
	int mid=(l+r)>>1;
	if (k<=mid) rs[y]=rs[x],add(l,mid,ls[x],ls[y],k);
	else ls[y]=ls[x],add(mid+1,r,rs[x],rs[y],k);
}
int qry(int x,int y,int k)
{
	int l=1,r=1000,used=0;
	x=rt[x-1];y=rt[y];
	if (s[y]-s[x]<h) return -1;
	while (l<r)
	{
		int mid=(l+r)>>1,t=s[rs[y]]-s[rs[x]];
		if (t<k) {used+=v[rs[y]]-v[rs[x]];k-=t;r=mid;x=ls[x];y=ls[y];}
		else {l=mid+1;x=rs[x];y=rs[y];}
	}
	used+=(k+l-1)/l;
	return used;
}
void work2()
{
	for (int i=1;i<=m;i++)
		t=read(),add(1,1000,rt[i-1],rt[i],t);
	while(T--)
	{
		x1=read(),y1=read(),x2=read(),y2=read(),h=read();
		int Ans=qry(y1,y2,h);
		if (Ans==-1)puts("Poor QLW");
		else printf("%d\n",Ans);
	}
}
int main()
{
	n=read(),m=read(),T=read();
	if (n!=1)work1();else work2();
	return 0;
}




©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页