【HDU 5532 Almost Sorted Array】水题,模拟

给出一个序列(长度>=2),问去掉一个元素后是否能成为单调不降序列或单调不增序列。

对任一序列,先假设其可改造为单调不降序列,若成立则输出YES,不成立再假设其可改造为单调不增序列,若成立则输出YES,不成立则输出NO。

由于持平不影响整体单调性,为了直观,我在以下把“不降”称为“递增/升序”,把“不增”称为“递减/降序”。

递增和递减是对称的,这里先考虑递增,递减改个符号和最值就好。

我们把为维护单调性而去掉的那个点称为“坏点”。由题目的要求,“可改造”可等价于“只存在一个坏点”。

对于“坏点”的判断,我们可以先找出是否只存在一组“逆序”。

对于“almosted sorted”递增序列,只存在一组逆序无非以下四种情况(这里先不考虑逆序在边界)。

现在考虑逆序在边界的情况。由于a[]数组元素下标是1~n,而此题1<=ai<=100000,那么对于递增序列,可把a[0]设为1、把a[n+1]设为100000作为首尾哨兵节点,一定不会破坏整体单调性;递减序列做对称的处理。这样边界也可以像中间一样处理。

由于三种情况满足一种即可,而第二种可以看作第三种和第四种的交集,故只需按照第三种和第四种的情况对a[]数组各进行一次遍历,满足一种即可输出YES。

对于坏点的处理,我们采用“当它不存在”的策略,所以首次遇到坏点,忽略它,再次遇到坏点,则此种情况不成立。

至于如何由“逆序”推出“坏点”,并实现几种情况的判断,我们遍历i:0~n,对于第一对逆序a[i]>a[i+1],我们可以:

先采取“左归”(第三种),即把a[i]当作坏点,判断a[i-1]和a[i+1]是否升序(若不升序则相当于构成了第二对逆序,出现第二个坏点);

若左归不成立,再采取“右归”(第四种),即把a[i+1]当坏点,同理判断a[i]和a[i+2]是否升序。

11.23更新代码如下,更加简化,速度更快

 1 #include <cstdio>
 2 using namespace std;
 3
 4 const int MAX_N=100005;
 5 const int MIN_A=1;
 6 const int MAX_A=100000;
 7 int T;
 8 int n;
 9 int a[MAX_N];
10 int flag;
11 int fix_cnt;
12
13 int main()
14 {
15     freopen("5532.txt","r",stdin);
16     scanf("%d",&T);
17     while(T--)
18     {
19         scanf("%d",&n);
20         for(int i=1;i<=n;i++)
21         {
22             scanf("%d",&a[i]);
23         }
24         //升序
25         flag=1;//假设去掉最多一个元素后整体降序
26         fix_cnt=0;
27         a[0]=MIN_A;
28         a[n+1]=MAX_A;
29         for(int i=1;i<=n-1;i++)
30         {
31             if(a[i]<=a[i+1]) continue;
32             fix_cnt++;
33             if(fix_cnt<=1&&(a[i-1]<=a[i+1]||a[i]<=a[i+2])) continue;
34             flag=0;
35             break;
36         }
37         if(flag)
38         {
39             printf("YES\n");
40             continue;
41         }
42         //降序
43         flag=1;//假设去掉最多一个元素后整体降序
44         fix_cnt=0;
45         a[0]=MAX_A;
46         a[n+1]=MIN_A;
47         for(int i=1;i<=n-1;i++)
48         {
49             if(a[i]>=a[i+1]) continue;
50             fix_cnt++;
51             if(fix_cnt<=1&&(a[i-1]>=a[i+1]||a[i]>=a[i+2])) continue;
52             flag=0;
53             break;
54         }
55         if(flag)
56         {
57             printf("YES\n");
58             continue;
59         }
60         printf("NO\n");
61     }
62     return 0;
63 }

先前版本代码如下:

 1 #include <cstdio>
 2 using namespace std;
 3
 4 const int MAX_N=100005;
 5 const int MIN_A=1;
 6 const int MAX_A=100000;
 7 int T;
 8 int n;
 9 int in[MAX_N],de[MAX_N];
10 int flag;
11 int fix_cnt;
12
13 int main()
14 {
15     freopen("5532.txt","r",stdin);
16     scanf("%d",&T);
17     while(T--)
18     {
19         scanf("%d",&n);
20         for(int i=1;i<=n;i++)
21         {
22             scanf("%d",&in[i]);
23             de[i]=in[i];
24         }
25
26         //升序的情况
27         in[0]=MIN_A;
28         in[n+1]=MAX_A;
29         flag=1;//假设去掉最多一个元素后整体升序
30         fix_cnt=0;
31         for(int i=1;i<=n-1;i++)
32         {
33             if(in[i]<=in[i+1]) continue;
34             fix_cnt++;//左归的情况
35             if(fix_cnt<=1&&in[i-1]<=in[i+1]) continue;
36             flag=0;
37             break;
38         }
39         if(flag)
40         {
41             printf("YES\n");
42             continue;
43         }
44         flag=1;
45         fix_cnt=0;
46         for(int i=1;i<=n-1;i++)
47         {
48             if(in[i]<=in[i+1]) continue;
49             fix_cnt++;//右归的情况
50             if(fix_cnt<=1&&in[i]<=in[i+2]) continue;
51             flag=0;
52             break;
53         }
54         if(flag)
55         {
56             printf("YES\n");
57             continue;
58         }
59         //降序的情况
60         de[0]=MAX_A;
61         de[n+1]=MIN_A;
62         flag=1;//假设去掉最多一个元素后整体降序
63         fix_cnt=0;
64         for(int i=1;i<=n-1;i++)
65         {
66             if(de[i]>=de[i+1]) continue;
67             fix_cnt++;//左归的情况
68             if(fix_cnt<=1&&de[i-1]>=de[i+1]) continue;
69             flag=0;
70             break;
71         }
72         if(flag)
73         {
74             printf("YES\n");
75             continue;
76         }
77         flag=1;
78         fix_cnt=0;
79         for(int i=1;i<=n-1;i++)
80         {
81             if(de[i]>=de[i+1]) continue;
82             fix_cnt++;//右归的情况
83             if(fix_cnt<=1&&de[i]>=de[i+2]) continue;
84             flag=0;
85             break;
86         }
87         if(flag)
88         {
89             printf("YES\n");
90             continue;
91         }
92         printf("NO\n");
93     }
94     return 0;
95 }

 

时间: 2024-11-02 16:22:24

【HDU 5532 Almost Sorted Array】水题,模拟的相关文章

HDOJ/HDU 1328 IBM Minus One(水题一个,试试手)

Problem Description You may have heard of the book '2001 - A Space Odyssey' by Arthur C. Clarke, or the film of the same name by Stanley Kubrick. In it a spaceship is sent from Earth to Saturn. The crew is put into stasis for the long flight, only tw

HDOJ(HDU) 1555 How many days?(水题)

Problem Description 8600的手机每天消费1元,每消费K元就可以获赠1元,一开始8600有M元,问最多可以用多少天? Input 输入包括多个测试实例.每个测试实例包括2个整数M, k,(2 <= k <= M <= 1000).M = 0, k = 0代表输入结束. Output 对于每个测试实例输出一个整数,表示M元可以用的天数. Sample Input 2 2 4 3 0 0 Sample Output 3 5 水题.... import java.util.

HDOJ/HDU 2537 8球胜负(水题.简单的判断)

Problem Description 8球是一种台球竞赛的规则.台面上有7个红球.7个黄球以及一个黑球,当然还有一个白球.对于本题,我们使用如下的简化规则:红.黄两名选手轮流用白球击打各自颜色的球,如果将该颜色的7个球全部打进,则这名选手可以打黑球,如果打进则算他胜.如果在打进自己颜色的所有球之前就把黑球打进,则算输.如果选手不慎打进了对手的球,入球依然有效. 现在给出打进的球(白球除外)的顺序,以及黑球由哪方打进,你的任务是判定哪方是胜者. 假设不会有一杆同时打进一颗黑球和其他彩球. Inp

HDOJ(HDU) 1562 Guess the number(水题,枚举就行)

Problem Description Happy new year to everybody! Now, I want you to guess a minimum number x betwwn 1000 and 9999 to let (1) x % a = 0; (2) (x+1) % b = 0; (3) (x+2) % c = 0; and a, b, c are integers between 1 and 100. Given a,b,c, tell me what is the

HDU 1228 模拟水题

字符串的水题 用了两种方法做的 感觉做法都很山寨 题目很水 如果不限制小于100会很好   #include <iostream> #include<cstdio> #include<cstring> using namespace std; int pd(string s) { if(s=="zero") return 0; if(s=="one") return 1; if(s=="two") return

acm水题 二叉树模拟 hdu5444,能想到的测试数据都测了还是WA,求大神

问题描述 acm水题 二叉树模拟 hdu5444,能想到的测试数据都测了还是WA,求大神 1)我的代码(题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5444,也有复制内容在代码下面) #include <iostream> #include <string.h> using namespace std; const int maxn=1010; char record[maxn]; int sum=0; struct tree{ i

[leetCode 第1题] -- Find Minimum in Rotated Sorted Array

题目链接: Find Minimun in Rotated Sorted Array 题目意思: 给定一个旋转数组,找出这个旋转数组的最小元素.旋转数组的定义是,把一个从小到大排好序的数组,取一部份放到末尾,例如0 1 2 4 5 6 7 取 0 1 2放到末尾,变成旋转数组4 5 6 7 0 1 2 代码:  class Solution { public: int findMin(vector<int> &num); }; int Solution::findMin(vector&

HDOJ/HDU 1256 画8(绞下思维~水题)

Problem Description 谁画8画的好,画的快,今后就发的快,学业发达,事业发达,祝大家发,发,发. Input 输入的第一行为一个整数N,表示后面有N组数据. 每组数据中有一个字符和一个整数,字符表示画笔,整数(>=5)表示高度. Output 画横线总是一个字符粗,竖线随着总高度每增长6而增加1个字符宽.当总高度从5增加到6时,其竖线宽度从1增长到2.下圈高度不小于上圈高度,但应尽量接近上圈高度,且下圈的内径呈正方形. 每画一个"8"应空一行,但最前和最后都无空

HDOJ(HDU) 1859 最小长方形(水题、、)

Problem Description 给定一系列2维平面点的坐标(x, y),其中x和y均为整数,要求用一个最小的长方形框将所有点框在内.长方形框的边分别平行于x和y坐标轴,点落在边上也算是被框在内. Input 测试输入包含若干测试用例,每个测试用例由一系列坐标组成,每对坐标占一行,其中|x|和|y|小于 231:一对0 坐标标志着一个测试用例的结束.注意(0, 0)不作为任何一个测试用例里面的点.一个没有点的测试用例标志着整个输入的结束. Output 对每个测试用例,在1行内输出2对整数