专栏文章
P3474 [POI 2008] KUP-Plot purchase 题解
P3474题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqd4zan
- 此快照首次捕获于
- 2025/12/04 02:51 3 个月前
- 此快照最后确认于
- 2025/12/04 02:51 3 个月前
草。
扔掉所有 的格子之后,如果能在剩下的格子中找到一个权值和 的矩形就有解。
证明:
如果存在一个格子权值在 之间直接选取它即可。为了方便,我们认为剩下的所有格子权值在 之间。
-
如果找到了这样的矩形,考察它的每一列:
- 如果它的权值在 之间,直接选取即可。
- 如果它的权值 ,从上往下依次删掉这一列的格子,因为格子的权值 ,所以必然存在一个时刻它的权值位于 之间(因为不会从 突变到 )。
- 所以我们只需考虑每一列权值 的情况,直接把每一列当成一个格子,套用上一种情况的构造即可。
-
如果不存在这样的矩形,显然无解。
因为每个格子的权值是非负整数,所以直接找极大的子矩形即可。
单调栈
CPPwhile 打成 if 调了一年。int main() {
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>k>>n;
auto ans=[&](int i1,int i2,int j1,int j2)->void{
cout<<j1<<" "<<i1<<" "<<j2<<" "<<i2<<'\n';
exit(0);
};
rep(i,1,n) {
rep(j,1,n) {
cin>>a[i][j];
if(a[i][j]>k+k)a[i][j]=-inf;
else if(a[i][j]>=k)ans(i,i,j,j);
}
}
rep(i,1,n)rep(j,1,n)pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+a[i][j];
auto s=[&](int i1,int i2,int j1,int j2)->ll {
return pre[i2][j2]-pre[i1-1][j2]-pre[i2][j1-1]+pre[i1-1][j1-1];
};
rep(i,1,n) {
rep(j,1,n) {
if(a[i][j]==-inf)h[j]=0;
else ++h[j];
}
stac[top=0]=0;
rep(j,1,n) {
while(top&&h[j]<=h[stac[top]])--top;
L[j]=stac[top]+1;
stac[++top]=j;
}
stac[top=0]=n+1;
per(j,n,1) {
while(top&&h[j]<=h[stac[top]])--top;
R[j]=stac[top]-1;
stac[++top]=j;
}
rep(j,1,n) {
if(s(i-h[j]+1,i,L[j],R[j])>=k) {
for(int i1=i-h[j]+1,i2=i,j1=L[j],j2=R[j]; j1<=j2; --j2) {
if(s(i1,i2,j1,j2)<=k+k)ans(i1,i2,j1,j2);
if(s(i1,i2,j2,j2)>k+k){
for(;i1<=i2;++i1)if(s(i1,i2,j2,j2)<=k+k)ans(i1,i2,j2,j2);
}
if(s(i1,i2,j2,j2)>=k)ans(i1,i2,j2,j2);
}
assert(0);
}
}
}
cout<<"NIE\n";
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...