CSP-S day2

1 动态仙人掌(cactus
1.1 题目描述
pufanyi 调到自闭了,于是决定修改题意。
和一般的孩子一样,小小迪是一个热爱科学的女孩子。
小小迪最近正在研究网线烧断的整个过程,于是钧钧家的 Chrome 就出现了
一些奇怪的锅……
于是钧钧就开始沉迷于拔网线。
为了更好地开这个隔膜,钧钧写了一个脚本,能自动识别仙人掌并自动跳。
考虑到钧钧装的是盗版的 Chrome,所以这个 Chrome 没有鸟,只有仙人掌。
钧钧找到了这个盗版 Chrome 的地图。这个盗版 Chrome 每次都会任选一段区间
[l, r] 开始游戏,小恐龙一开始在 l,如果跑到了 r,那么 Chrome 就会判她通关。
当然了,如果起点处有仙人掌,那就不可能通关了,如果终点处有仙人掌是没有关
系的, 因为在 r 时小恐龙可以不在地上(它会跳)
然而钧钧发现她不能控制跳的高度,所以每次跳跃的最高点高度是一定的,均为 k
这个盗版 Chrome 的跳跃很假,跳跃时与地面呈 45 度夹角,跳到最高点时立即下
落,下落时也与地面呈 45 度夹角, 上升和下降均做直线运动
小恐龙能开始跳跃当且仅当他当前位置是在地面上而不是在空中,小恐龙能跳过仙
人掌当且仅当它在仙人掌所在横坐标时纵坐标大于等于仙人掌的高度。
钧钧玩了好多次小恐龙,已知第 i 次系统选择的区间为 [li, ri],钧钧很想知道每次
游戏她是否能通关。
如果不是很熟悉小恐龙的同学可以现在打开 Chrome 玩一玩。
也可以Chrome 打开 chrome://dino,效果更佳。

1.2 输入输出格式
1.2.1 输入格式

 


从文件 cactus.in 中读入数据。
第一行三个正整数 n, k, q 表示仙人掌个数,小恐龙每次跳跃的最高点高度以及询
问次数。
接下来 n 行,每行两个正整数 xi, hi,表示每个仙人掌的横坐标与高度。
接下来 q 行,每行两个正整数 li, ri 表示一次询问。
输入保证 xi 互不相同。
1.2.2 输出格式
输出到文件 cactus.out 中。
输出一共 q 行,第 i 行对应着第 i 个询问。
对于每个询问,如果钧钧可以到达终点,那么输出 Yes,否则输出 No
1.3 样例
1.3.1 样例 1 输入
2 1 4
2 1
4 3
1 3
3 5
1 2
2 3
1.3.2 样例 1 输出
Yes
No
Yes
No
1.3.3 样例 1 解释
1 动态仙人掌(CACTUS4
1.3.4 样例 2 输入
5 1 3
5 9
1 9
8 1
4 7
10 3
3 20
6 15
15 15
1.3.5 样例 2 输出
No
No
Yes
1.4 数据范围与提示
本题共 10 个测试点,每个测试点 10 分。
对于所有测试点,均有 hi 109, k 50, 1 li ri 109
每个测试点的具体限制见下表。

测试点编号 n q max{xi}
1 2 3 10 10
3 5 100 100 500
6 8 500 10000 10000
9 10000 50000 100000
10 50000 100000 1000000

 

 

 

 


本题数据很弱,欢迎各种乱搞。

 

一开始看到这题的时候,想到2018年day1T1,便思考是不是有奇特的办法去解决,毕竟是T1嘛(事实证明我太天真了)

想了几种办法之后,发现实在想不出来,总不是正解,便想打个模拟大暴力(暴力都不会打,AFO警告)

艰难地打了个复杂度很高的大暴力并且成功地过了样例之后,我就去水了。

然鹅不出所料,直接10分(哭泣)

 

但其实正解也是个十分暴力的DP,复杂度为k*q+xxx

设一个dp数组为dp[N][k][2],//当前状态为在N,高度是K,想对于前一个位置是上升0,还是下降1,能到达的最远距离,最后只需要把这个距离和R进行比较即可

总的思路就是从右到左,枚举上一个位置的状态,bf的DP(我菜菜我菜菜)

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 inline int read(){
 5     int f=0,num;
 6     char ch;
 7     while(ch=getchar(),!isdigit(ch))if(ch=='-')f=1;num=ch-'0';
 8     while(ch=getchar(),isdigit(ch))num=num*10+ch-'0';
 9     return f?-num:num;
10 }
11 const int N=50003,K=53,INF=1e9+3;
12 int n,k,q,h[N],dp[N][K][2];//当前状态为在N,高度是K,想对于前一个位置是上升0,还是下降1
13 int far;
14 int maxn(int a,int b,int c,int d){
15     a>=b?a:b;
16     a>=c?a:c;
17     a>=d?a:d;
18     return a;
19 }
20 int main(){
21     freopen("cactus.in","r",stdin);
22     freopen("cactus.out","w",stdout);
23     n=read();k=read();q=read();
24     for(int i=1;i<=n;i++){
25         int a,b;
26         a=read();b=read();
27         h[a]>b?h[a]:b;
28         far>a?far:a;
29     }
30     for(int i=0;i<=k;i++)
31         dp[far+1][i][0]=dp[far+1][i][1]=INF;
32     for(int i=far;i;i--){//从右往左 
33         for(int j=h[i];j<k;j++){//从最右边的仙人掌出发,枚举高度
34             dp[i][j][0]=maxn(i,dp[i+1][j+1][0]);
35             dp[i][j][1]=maxn(i,dp[i+1][j-1][1]);
36         }
37         if(!h[i]){//没有仙人掌,只能在地上走或者跳 
38             dp[i][0][0]=dp[i][0][1]=maxn(i,dp[i+1][0][0],dp[i+1][0][1],dp[i+1][1][0]);
39             // dp[i+1][0][0],dp[i+1][0][1]走,dp[i+1][1][0]相对于dp[i][0][0]=dp[i][0][1]一定是上升的 
40         }
41         if(h[i]<=k)//到顶了 只能往下掉
42             dp[i][k][0]=dp[i][k][1]=max(i,dp[i+1][k-1][1]);
43     }    
44     for(int i=1;i<=q;i++)
45     {
46         int l=read(),r=read();
47         if(l>far||maxn(dp[l][0][0],dp[l][0][1])>=r)
48             printf("Yes
");
49         else
50             (maxn(dp[l][0][0],dp[l][0][1])>=r)?printf("Yes
"):printf("No
");
51     }
52     fclose(stdin);fclose(stdout);    
53     return 0; 
54 } 

我太难了!

(爆零警告)

原文地址:https://www.cnblogs.com/Shayndel/p/11828909.html