[NOIP2011 提高组] 铺地毯
题目描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n n n 张地毯,编号从 1 1 1 到 n n n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入格式
输入共 n + 2 n + 2 n+2 行。
第一行,一个整数 n n n,表示总共有 n n n 张地毯。
接下来的 n n n 行中,第 i + 1 i+1 i+1 行表示编号 i i i 的地毯的信息,包含四个整数 a , b , g , k a ,b ,g ,k a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 ( a , b ) (a, b) (a,b) 以及地毯在 x x x 轴和 y y y 轴方向的长度。
第 n + 2 n + 2 n+2 行包含两个整数 x x x 和 y y y,表示所求的地面的点的坐标 ( x , y ) (x, y) (x,y)。
输出格式
输出共 1 1 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 -1
。
样例 #1
样例输入 #1
3
1 0 2 3
0 2 3 3
2 1 3 3
2 2
样例输出 #1
3
样例 #2
样例输入 #2
3
1 0 2 3
0 2 3 3
2 1 3 3
4 5
样例输出 #2
-1
提示
【样例解释 1】
如下图, 1 1 1 号地毯用实线表示, 2 2 2 号地毯用虚线表示, 3 3 3 号用双实线表示,覆盖点 ( 2 , 2 ) (2,2) (2,2) 的最上面一张地毯是 3 3 3 号地毯。
【数据范围】
对于 30 % 30\% 30% 的数据,有 n ≤ 2 n \le 2 n≤2。
对于 50 % 50\% 50% 的数据, 0 ≤ a , b , g , k ≤ 100 0 \le a, b, g, k \le 100 0≤a,b,g,k≤100。
对于 100 % 100\% 100% 的数据,有 0 ≤ n ≤ 1 0 4 0 \le n \le 10^4 0≤n≤104, 0 ≤ a , b , g , k ≤ 10 5 0 \le a, b, g, k \le {10}^5 0≤a,b,g,k≤105。
noip2011 提高组 day1 第 1 1 1 题。
题解
解题思路
本题是一个很简单的模拟题
因为这道题所占用的空间较大,如果进行遍历数组地图的方法无论是空间复杂度还是时间复杂度都会变得很复杂
所以,不妨进行分析,其实每个地毯只需要5个数据就好,这样能大大的加大空间利用率,也不必去遍历那些无用的空间。 每张地毯所需要的数据无非是左下角坐标x,y,右上角坐标x,y和地毯编号。 只要点在地毯范围内,最后取编号最大的输出即可。
一开始开个二维数组去搞,没看到数据范围…MLE… ( Q A Q ) (QAQ) (QAQ),换成结构体数组就 A C AC AC了
考点
模拟 枚举
时间复杂度
O ( N ) O(N) O(N)
AC代码
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
long long read(){
long long ans=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
f*=(ch=='-')?-1:1;
ch=getchar();
}
while(isdigit(ch)){
ans=(ans<<1)+(ans<<3)+(ch^48);
ch=getchar();
}
return ans*f;
}
const int MAXN=1e5+5;
long long n,xx,yy,di=-1;
struct dt{
long long a,b,x,y;
}d[MAXN];
int main(){
n=read();
for(int i=1;i<=n;i++){
d[i].a=read();
d[i].b=read();
d[i].x=read();
d[i].y=read();
}
xx=read();
yy=read();
for(int i=1;i<=n;i++){
if(xx>=d[i].a&&xx<=d[i].a+d[i].x&&yy>=d[i].b&&yy<=d[i].b+d[i].y){
di=i;
}
}
printf("%lld",di);
return 0;
}
[NOIP2011 提高组] 选择客栈
题目描述
丽江河边有 n n n 家很有特色的客栈,客栈按照其位置顺序从 1 1 1 到 n n n 编号。每家客栈都按照某一种色调进行装饰(总共 k k k 种,用整数 0 ∼ k − 1 0 \sim k-1 0∼k−1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p p p 。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p p p 元的咖啡店小聚。
输入格式
共 n + 1 n+1 n+1 行。
第一行三个整数 n , k , p n, k, p n,k,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的 n n n 行,第 i + 1 i+1 i+1 行两个整数,之间用一个空格隔开,分别表示 $i $ 号客栈的装饰色调 a i a_i ai 和 i i i 号客栈的咖啡店的最低消费 b i b_i bi。
输出格式
一个整数,表示可选的住宿方案的总数。
样例 #1
样例输入 #1
5 2 3
0 5
1 3
0 2
1 4
1 5
样例输出 #1
3
提示
样例解释
2 人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,但是若选择住 4 , 5 4,5 4,5号客栈的话, 4 , 5 4,5 4,5 号客栈之间的咖啡店的最低消费是 4 4 4 ,而两人能承受的最低消费是 3 3 3 元,所以不满足要求。因此只有前 3 3 3 种方案可选。
数据范围
- 对于 30 % 30\% 30% 的数据,有 n ≤ 100 n \leq 100 n≤100 ;
- 对于 50 % 50\% 50% 的数据,有 n ≤ 1 000 n \leq 1\,000 n≤1000;
- 对于 100 % 100\% 100% 的数据,有 2 ≤ n ≤ 2 × 1 0 5 2 \leq n \leq 2 \times 10^5 2≤n≤2×105, 1 ≤ k ≤ 50 1 \leq k \leq 50 1≤k≤50, 0 ≤ p ≤ 100 0 \leq p \leq 100 0≤p≤100, 0 ≤ b i ≤ 100 0 \leq b_i \leq 100 0≤bi≤100。
题解
解题思路
简单来讲就是在一段一维客栈中,任意选择两个客栈 a 、 b a、b a、b,满足以下两个条件:
1. a 、 b a、b a、b颜色相同,
2. [ a , b ] [a,b] [a,b]闭区间之间必须存在某个客栈的咖啡店的花费小于等于 p p p;
因为我们要找到所有成立的 a 、 b a、b a、b,那么我们就枚举每个 b b b 想办法找到此时符合条件的a有多少个
用一个变量t记录的是当前枚举客栈过程中,离我们枚举到的客栈最近的最低消费小于等于 p p p的客栈的下标(第几个客栈)
开个数组 ( n u m [ ] ) (num[ ]) (num[])实时更新在t前面的各个颜色的客栈有多少个;
当然我们还用了一个 c o l o r color color数组记录每个客栈的颜色,这样我们就得到了答案
考点
递推
时间复杂度
O ( N ) O(N) O(N)
AC代码
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
long long read(){
long long ans=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
f*=(ch=='-')?-1:1;
ch=getchar();
}
while(isdigit(ch)){
ans=(ans<<1)+(ans<<3)+(ch^48);
ch=getchar();
}
return ans*f;
}
const int MAXN=200005;
long long n,k,p,t,ans,price,num[110],color[MAXN];
int main(){
n=read();
k=read();
p=read();
for(int i=1;i<=n;i++){
color[i]=read();
price=read();
if(price<=p) {
for(int j=i;j>t;j--){
num[color[j]]++;
}
t=i;
ans+=num[color[i]]-1;
}
else{
ans+=num[color[i]];
}
}
printf("%lld",ans);
return 0;
}
[NOIP2011 提高组] Mayan 游戏
题目描述
Mayan puzzle 是最近流行起来的一个游戏。游戏界面是一个 7 7 7 行 × 5 \times5 ×5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:
- 每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见输入输出样例说明中的图 6 6 6 到图 7 7 7);如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图 1 1 1 和图 2 2 2);
- 任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。
注意:
a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图 4 4 4,三个颜色为 1 1 1 的方块和三个颜色为 2 2 2 的方块会同时被消除,最后剩下一个颜色为 2 2 2 的方块)。
b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形, 5 5 5 个方块会同时被消除)。
- 方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。
上面图 1 1 1 到图 3 3 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为 ( 0 , 0 ) (0,0) (0,0),将位于 ( 3 , 3 ) (3,3) (3,3) 的方块向左移动之后,游戏界面从图 1 1 1 变成图 2 2 2 所示