Hi,朋友们。又见面了。上次我们做了一道美国题,这次我们来干一道“国产”题目
(本文适合学习C++有那么一点点基础,但基础又不是特别高的朋友)
A.题目描述
题目描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有n 张地毯,编号从1 到n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入
输入共 n+2 行。
第一行,一个整数 n,表示总共有n 张地毯。
接下来的 n 行中,第i+1 行表示编号i 的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y 轴方向的长度。
第 n+2 行包含两个正整数x 和y,表示所求的地面的点的坐标(x,y)。
输出
输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。
样例输入
样例1:
3
1 0 2 3
0 2 3 3
2 1 3 3
2 2
样例2:
3
1 0 2 3
0 2 3 3
2 1 3 3
4 5
样例输出
样例1:
3
样例2:
-1
提示
对于 30%的数据,有n≤2;
对于 50%的数据,0≤a, b, g, k≤100;
对于 100%的数据,有0≤n≤10,000,0≤a, b, g, k≤100,000。
来源
NOIP2011
B.初步分析
如果使用二维数组……
二维数组,感觉是这种题名正言顺的做法……
这是一个网格——

名义上二维数组是行得通的,只需要定义这么大的个数组,然后一层层往上面铺,再查询某个坐标面上的是那张地毯——
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&a,&b,&g,&k);
for(int j=b;j<=b+k;j++){
for(int l=a-g;l<=a;l++){
p[j][l]=i;
}
}
}
if(p[x][y]==0){//查看这个点最上层是哪张地毯
printf("-1");
}
else
printf("%d",p[x][y]);
那么我们现在就面临了一个一个问题——二维数组开多大?
1.p[10001][10001]
于是——运行错误

2.p[100001][100001]
于是——编译错误



哈哈哈哈,又被我耍了……
(如果你想知道这是为什么,文档后面E.3处有介绍)
C.改进算法
我们来看这一幅图:

从中我们想:如果我们预先设定好要查询的位置,再来查询,会不会快点呢?
看代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a[10000],b[10000],x[10000],y[10000],c,d;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&a[i],&b[i],&x[i],&y[i]);//任它先输入
}
scanf("%d%d",&c,&d);
int m=-1;
for(int i=n;i>=1;i--){//更省时哟
if(c>=a[i]&&c<=a[i]+x[i]&&d<=b[i]+y[i]&&d>=b[i]){//范围查找
m=i;
printf("%d",m);
return 0;
}
}
printf("-1");
return 0;
}
这道题就完事了。
D.补充模块
1.喜闻见乐的NOIP介绍:
NOIP比赛
NOIP(National Olympiad in Informatics in Provinces,全国青少年信息学奥林匹克联赛)是一项面向全国青少年的信息学竞赛和普及活动。为NOI主管的一系列比赛之一,旨在向那些在中学阶段学习的青少年普及计算机科学知识,给学校的信息技术教育课程提供动力和新的思路;给那些有才华的学生提供相互交流和学习的机会。通过竞赛和相关的活动培养选拔优秀的计算机人才。初、高中或其他中等专业学校的学生可报名参加联赛。
竞赛形式:
竞赛赛制:
联赛分两个年龄组:初中组和高中组(普及组和提高组)。每组竞赛分两轮:初试和复试。各省市初试成绩在本赛区前百分之十五的学生进入复赛。
初试形式为笔试,侧重考察学生的计算机基础知识和编程的基本能力,并对知识面的广度进行测试。
复试形式为上机,侧重考察学生对问题的分析理解能力,数学抽象能力,驾驭编程语言的能力和编程技巧、想象力和创造性等。
初赛及复赛程序设计采用C、C++、Pascal语言,2022年后将不可使用Pascal、C语言,只能使用C++。
赛程赛事:
初赛:十月的第2个或第3个星期六下午14:30-16:30(普及,提高)
复赛:十一月的第2个星期六下午14:30-18:00(普及组)
十一月的第2个星期六上午8:30-12:00,星期日上午8:30-12:00(共2天,提高组)
自2017年来,由于参赛人数增多,NOIP复赛规模的规则进行了调整。包括:每个省赛区可以设立多于两个的复赛考点(但必须在同一个城市),初赛进入复赛的比例和规模由各省赛区自行决定,在条件许可的情况下,鼓励更多选手参赛。同时复赛获奖比例将基本保持不变,全国一等奖获奖比例约为复赛参赛选手的20%。
2.NOI网上报名系统
链接在此。
因为是中文界面,我就不演示了。
3.为什么会有这种效果
二维数组,假如是a[N][N],在128M空间的限制下,最多N不超过3000。因为9千万开根号是3000,而a[N][M],N*M不能大于9千万。
E.同主题文章链接
【信息学竞赛真题! ! !】「USACO2016」Subsequences Summing to Sevens题解(C++版)

本文介绍了NOIP2011竞赛中的一道铺地毯问题,探讨了使用二维数组和改进算法解决该问题的思路。通过对输入数据的分析和算法优化,实现了高效查询地面某点被哪张地毯覆盖。适合有一定C++基础的信息学竞赛学习者。
763

被折叠的 条评论
为什么被折叠?



