[Codeforces599C] Day at the Beach (贪心)

  • 题目概述:

  One day Squidward, Spongebob and Patrick decided to go to the beach. Unfortunately, the weather was bad, so the friends were unable to ride waves. However, they decided to spent their time building sand castles.

  At the end of the day there were n castles built by friends. Castles are numbered from 1 to n, and the height of the i-th castle is equal tohi. When friends were about to leave, Squidward noticed, that castles are not ordered by their height, and this looks ugly. Now friends are going to reorder the castles in a way to obtain that condition hi ≤ hi + 1 holds for all i from 1 to n - 1.

  Squidward suggested the following process of sorting castles:

    1. Castles are split into blocks — groups of consecutive castles. Therefore the block from i to j will include castles i, i + 1, ..., j. A block may consist of a single castle.
    2. The partitioning is chosen in such a way that every castle is a part of exactly one block.
    3. Each block is sorted independently from other blocks, that is the sequence hi, hi + 1, ..., hj becomes sorted.
    4. The partitioning should satisfy the condition that after each block is sorted, the sequence hi becomes sorted too. This may always be achieved by saying that the whole sequence is a single block.

  Even Patrick understands that increasing the number of blocks in partitioning will ease the sorting process. Now friends ask you to count the maximum possible number of blocks in a partitioning that satisfies all the above requirements.

  有一些沙子堆的城堡,现让你给这些城堡分成若干组,使得每一组的城堡是连续的,每一个城堡都必须在一个组里,且对每一组升序排序后,所有的沙堡都排好了序,问最多可分几组?

  • 输入格式:

  第一行一个整数n(1 ≤ n ≤ 100 000),表示城堡的数目;

  第二行包括n个整数h1, h2, ..., hn(1 ≤ hi ≤ 10^9),表示每一个城堡的高度。

  • 输出格式:

  一个整数,表示最多可分的组数。

  • 样例输入1:

  3

  1 2 3

  • 样例输出1:

  3

  • 样例输入2:

  4

  2 1 3 2

  • 样例输出2:

  2

  • 思路:

  比赛时我是这么想的:

  如果[i, j]可以被分为一组,那么将原序列排好序后,[i, j]上每一个数的个数应和未排序时[i, j]上每一个数的个数相同,例如样例2:

    未排序:2 1 3 2

    已排序:1 2 2 3

  在两个序列的[1, 2]中1均出现1次,2均出现1次,在[3, 4]中2均出现1次,3均出现1次。

  所以设一个bool类型的数组,用来存某一个数字在两个序列中出现次数是否相同。

  然后,然后我就傻傻地写了个线段树:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 100005;
 4 int a[MAXN], b[MAXN], c[MAXN], x;
 5 bool seg[MAXN * 3];
 6 map<int, int> Map;
 7
 8 void update(int o, int l, int r) {
 9     int mid = l + r >> 1;
10     if(l == r) {
11         seg[o] = !!c[l]; return;
12     }
13     if(x <= mid) update(o << 1, l, mid);
14     else update(o << 1 | 1, mid + 1, r);
15     seg[o] = seg[o << 1] | seg[o << 1 | 1];
16 }
17
18 int main() {
19     int n, ans = 0;
20     scanf("%d", &n);
21     for(int i = 1; i <= n; i++) {
22         scanf("%d", a + i);
23         b[i] = a[i];
24     }
25     sort(b + 1, b + n + 1);
26     for(int i = 1; i <= n; i++)
27         Map[b[i]] = i;
28     for(int i = 1; i <= n; i++) {
29         a[i] = Map[a[i]]; b[i] = Map[b[i]];
30     }
31     for(int i = 1; i <= n; i++) {
32         c[a[i]]++; c[b[i]]--;
33         x = a[i]; update(1, 1, n);
34         x = b[i]; update(1, 1, n);
35         if(!seg[1]) ans++;
36     }
37     printf("%d\n", ans);
38     return 0;
39 }

  考完后舔了舔题解,才发现自己是多傻:

  因为最终结果是升序,所以对于一个i,只要min(hi+1, hi+2, ..., hn) ≤ max(h1, h2, ..., hi),那么i以及之前没有分组的数可分为一组:  

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 100005;
 4 int a[MAXN], mina[MAXN], maxa[MAXN], x;
 5
 6 int main() {
 7     int n, ans = 0;
 8     scanf("%d", &n);
 9     for(int i = 1; i <= n; i++)
10         scanf("%d", a + i);
11     maxa[1] = a[1]; mina[n] = a[n];
12     for(int i = 2; i <= n; i++)
13         maxa[i] = max(maxa[i - 1], a[i]);
14     for(int i = n - 1; i; i--)
15         mina[i] = min(mina[i + 1], a[i]);
16     for(int i = 1; i <= n; i++)
17         if(maxa[i] <= mina[i + 1]) ans++;
18     printf("%d\n", ans + 1);
19     return 0;
20 }
时间: 2024-08-05 02:20:06

[Codeforces599C] Day at the Beach (贪心)的相关文章

Codeforces 553D Nudist Beach(图论,贪心)

Solution: 假设已经选了所有的点. 如果从中删掉一个点,那么其它所有点的分值只可能减少或者不变. 如果要使若干步删除后最小的分值变大,那么删掉的点集中肯定要包含当前分值最小的点. 所以每次删掉一个点都记录一次最大值.取最大的情况输出就好. #include <bits/stdc++.h> using namespace std; const int N = 100009; vector<int> E[N], out; set<pair<double, int&g

Sunscreen (poj 3614 贪心+优先队列)

Language: Default Sunscreen Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4499   Accepted: 1565 Description To avoid unsightly burns while tanning, each of the C (1 ≤ C ≤ 2500) cows must cover her hide with sunscreen when they're at th

POJ3614 Sunscreen 【贪心】

Sunscreen Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4204   Accepted: 1458 Description To avoid unsightly burns while tanning, each of the C (1 ≤ C ≤ 2500) cows must cover her hide with sunscreen when they're at the beach. Cow i has

【uva 1615】Highway(算法效率--贪心 区间选点问题)

题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到一个个区间,这样就是选最小的点覆盖所有的区间的问题了.我之前的一篇博文有较详细的解释:关于贪心算法的经典问题(算法效率 or 动态规划).代码实现我先空着.挖坑~

【贪心+Treap】BZOJ1691-[Usaco2007 Dec]挑剔的美食家

[题目大意] 有n头奶牛m种牧草,每种牧草有它的价格和鲜嫩度.每头奶牛要求它的牧草的鲜嫩度要不低于一个值,价格也不低于一个值.每种牧草只会被一头牛选择.问最少要多少钱? [思路] 显然的贪心,把奶牛和牧草都按照鲜嫩度由大到小排序,对于每奶牛把鲜嫩度大于它的都扔进treap,然后找出后继. 不过注意后继的概念是大于它且最小的,然而我们这里是可以等于的,所以应该是找cow[i].fresh-1的后继,注意一下…… 1 #include<iostream> 2 #include<cstdio&

POJ1017 Packets(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 51306          Accepted: 17391 Description A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These pro

ZOJ 3946 Highway Project 贪心+最短路

题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3946 题解: 用dijkstra跑单元最短路径,如果对于顶点v,存在一系列边(ui,v)使得dis[v]最小(dis[v]表示0到v的距离).这些边能且只能选一条,那么我们自然应该选cost最小的那个边了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #inc

CoderForce 140C-New Year Snowmen(贪心)

题目大意:有n个已知半径的雪球.堆一个雪人需要三个尺寸不同的雪球,问用这些雪球最多能堆多少个雪人? 题目分析:先统计一下每种尺寸的球的个数,从三种最多的种类中各取出一个堆成雪人,这样贪心能保证的到的数目最多. 代码如下: # include<iostream> # include<map> # include<vector> # include<cstdio> # include<queue> # include<algorithm>

计蒜客 跳跃游戏(贪心)

给定一个非负整数数组,假定你的初始位置为数组第一个下标.数组中的每个元素代表你在那个位置能够跳跃的最大长度. 请确认你是否能够跳跃到数组的最后一个下标. 例如: A = [2,3,1,1,4], return ture A = [3,2,1,0,4], return false. 格式: 第一行输入一个正整数n,接下来的一行,输入数组A[n].如果能跳到最后一个下标,输出"true",否则输出"false" 样例1 ????输入:???? ????????5 ???