题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1926
题意:
思路:(1)对于R、C<=200的,用f[i][j][k]表示到达(i,j)数字k出现的次数。对于询问暴力统计即可;
(2)对于R=1的,用线段树套个treap,二分查询。
struct node
{
int val,size,pri,L,R,cnt,sum;
};
node a[N*27];
int e;
int newNode(int val)
{
int x=++e;;
a[x].val=val;
a[x].sum=val;
a[x].size=1;
a[x].cnt=1;
a[x].L=a[x].R=0;
a[x].pri=rand();
return x;
}
void pushUp(int x)
{
if(x==0) return;
a[x].size=a[x].cnt+a[a[x].L].size+a[a[x].R].size;
a[x].sum=a[x].cnt*a[x].val+a[a[x].L].sum+a[a[x].R].sum;
}
void rotL(int &x)
{
int y=a[x].R;
a[x].R=a[y].L;
a[y].L=x;
pushUp(x);
pushUp(y);
x=y;
}
void rotR(int &x)
{
int y=a[x].L;
a[x].L=a[y].R;
a[y].R=x;
pushUp(x);
pushUp(y);
x=y;
}
void insert(int &k,int val)
{
if(k==0) k=newNode(val);
else if(val<a[k].val)
{
insert(a[k].L,val);
if(a[a[k].L].pri>a[k].pri) rotR(k);
}
else if(val>a[k].val)
{
insert(a[k].R,val);
if(a[a[k].R].pri>a[k].pri) rotL(k);
}
else a[k].cnt++;
pushUp(k);
}
int d[N],sum[N];
pair<int,int> getCnt(int t,int x)
{
if(t==0) return MP(0,0);
int cnt,sum;
if(a[t].val==x)
{
cnt=a[a[t].R].size+a[t].cnt;
sum=a[a[t].R].sum+a[t].cnt*a[t].val;
return MP(cnt,sum);
}
if(a[t].val<x) return getCnt(a[t].R,x);
pair<int,int> p=getCnt(a[t].L,x);
p.first+=a[t].cnt+a[a[t].R].size;
p.second+=a[t].cnt*a[t].val+a[a[t].R].sum;
return p;
}
struct Node
{
int L,R,root;
};
Node A[N<<2];
void build(int t,int L,int R)
{
A[t].L=L;
A[t].R=R;
A[t].root=newNode(d[L]);
int i;
for(i=L+1;i<=R;i++) insert(A[t].root,d[i]);
if(L==R) return;
int M=(L+R)>>1;
build(t*2,L,M);
build(t*2+1,M+1,R);
}
pair<int,int> search(int t,int L,int R,int x)
{
if(A[t].L==L&&A[t].R==R) return getCnt(A[t].root,x);
int M=(A[t].L+A[t].R)>>1;
if(R<=M) return search(t*2,L,R,x);
if(L>M) return search(t*2+1,L,R,x);
pair<int,int> p,q;
p=search(t*2,L,M,x);
q=search(t*2+1,M+1,R,x);
p.first+=q.first;
p.second+=q.second;
return p;
}
void cal(int L,int R,int x)
{
if(sum[R]-sum[L-1]<x)
{
puts("Poor QLW");
return;
}
pair<int,int> p;
int low=0,high=1001,mid,t;
while(low<=high)
{
mid=(low+high)>>1;
p=search(1,L,R,mid);
if(p.second<x) high=mid-1;
else low=mid+1,t=mid;
}
p=search(1,L,R,t+1);
PR((x-p.second-1)/t+1+p.first);
}
int f[201][201][1001];
int n,m,Q;
void deal1()
{
int i;
FOR1(i,m) RD(d[i]),sum[i]=sum[i-1]+d[i];
build(1,1,m);
int x1,y1,x2,y2,S;
while(Q--)
{
RD(x1,y1); RD(x2,y2); RD(S);
cal(y1,y2,S);
}
}
int get(int x1,int y1,int x2,int y2,int t)
{
return f[x2][y2][t]-f[x2][y1-1][t]-f[x1-1][y2][t]+f[x1-1][y1-1][t];
}
void deal2()
{
int i,j,k,x;
FOR1(i,n) FOR1(j,m)
{
RD(x);
FOR1(k,1000) f[i][j][k]=f[i-1][j][k]+f[i][j-1][k]-f[i-1][j-1][k];
f[i][j][x]++;
}
int x1,y1,x2,y2,S;
int cnt,sum,temp;
while(Q--)
{
RD(x1,y1); RD(x2,y2); RD(S);
sum=0; cnt=0;
for(i=1000;i>=1;i--)
{
temp=get(x1,y1,x2,y2,i);
if(sum+temp*i<S) sum+=temp*i,cnt+=temp;
else
{
cnt+=(S-sum-1)/i+1;
break;
}
}
if(i>=1) PR(cnt);
else puts("Poor QLW");
}
}
int main()
{
RD(n,m,Q);
if(n==1) deal1();
else deal2();
}