题面(不完整,意思大致如此)
CACC算法能力大赛第三题
复盘后的题目

与原来的描述存在一些出入,这些不要紧。
问题采用捆绑测试,只有一组的所有点都过了这点才算分
组1 n<500 k=0
组2 n<5000 k=0
组3 n<500 k任意
组4 n<5000 k任意
暴力解法
cpp
#include<iostream>
#define i64 long long
using namespace std;
i64 lt,rt,w,n,ans=-1e18;
i64 x[5005],y[5005];//存坐标
int main(){
cin>>lt>>rt>>w>>n;
for(i64 i=1;i<=n;i++)
cin>>x[i]>>y[i];
x[n+1]=0,y[n+1]=0;
x[n+2]=lt,y[n+2]=0;
x[n+3]=0,y[n+3]=rt;
x[n+4]=lt,y[n+4]=rt;
//加上四个角的四个点
for(i64 i=1;i<=n+4;i++){
for(i64 j=1;j<=n+4;j++){//i,j就是目标的两个位置
if(j==i) continue;//重合位
if(x[i]==x[j]&&y[i]==y[j]) continue;//重合点
i64 l=min(x[i],x[j]),r=max(x[i],x[j]);//左右
i64 d=min(y[i],y[j]),u=max(y[i],y[j]);//上下
if(l==r){//处理垂直线的情况
if(l<rt-l) r=rt;
else l=0;
}
if(d==u){//处理水平线的情况
if(d<lt-d) u=lt;
else d=0;
}
i64 cnt=0;//统计四点的钉子数
bool flag=1;//钉子不在里面
for(i64 k=1;k<=n;k++){//这里不加4
if(x[k]<r && x[k]>l && y[k]<u && y[k]>d){
flag=0;
break;//钉子在范围内
}
if(x[k]==r&&y[k]==u) cnt++;
else if(x[k]==r&&y[k]==d) cnt++;
else if(x[k]==l&&y[k]==u) cnt++;
else if(x[k]==l&&y[k]==d) cnt++;
}
if(flag==1){
i64 res=(r-l)*(u-d)-w*(4-cnt);
ans=max(res,ans);
}
}
}
cout<<ans;
}
结果:第一组全死,第三组AC8WA2。
调了两个小时,无果,遂返。
这题暴力法O(n^3),所以也是注定了我只能去搞1、3组点,但是就是这样也一分没捞到。
现在再回来研究,就发现了一个惊天大bug:
i64 l=min(x[i],x[j]),r=max(x[i],x[j]);//左右
i64 d=min(y[i],y[j]),u=max(y[i],y[j]);//上下
去盘这个代码的逻辑就发现,lrdu写反了。
那么为什么我当时没查出来?

现在AI分析我的代码,这么做为什么会错。

正解
听说是:离散化+前缀和+二分。
考试的时候想过前缀和,但是根本想不明白这玩意怎么前缀和。
我也懒得学了,就这样吧。。。