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;
}