打气球



问题

 

大房间里飘着N个气球。气球从左到右排成一列。珍苏喜欢用箭训练打猎。珍苏从左到右射箭。

高度是随意选择的。箭是在选择的高度H上,往面向气球的方向从左到右移动。箭面向气球的瞬间,气球会爆炸,然后消失。然后箭继续往右移动时,高度会降低1。所以在高度H上移动的箭,打破气球后,高度会成为H-1

我们的目标是打破所有气球时,尽量使用最少的箭。

输入

 

第一行,会给出整数N(1 ≤ N ≤ 1 000 000)

第二行,会给出N Hi排列。

每个Hi(1 ≤ Hi ≤ 1 000 000)是第i个气球的高度,是从左到右罗列的顺序。

输出

第一个行上输出最少需要的箭数量。

案例输入 1

5

2 1 5 4 3

案例输出1

2

案例输入2

5

1 2 3 4 5

案例输出2

5

案例输入3

5

4 5 2 1 4

案例输出3

3

 

 


 

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <set>

 

using namespace std;

 

const int MAXN = 1 << 20;

 

int n;

 

set <int> S[MAXN];

int find (int pos, int v) {

 set<int>::iterator it = S[v].lower_bound(pos);

  if(it == S[v].end()) return -1;

 return *it;

}

 

int v[MAXN];

 

int main (void){

 scanf("%d", &n);

  for(int i = 0; i < n; ++i) {

   scanf("%d", &v[i]);

   S[v[i]].insert(i);

  }

 

  intans = 0;

  for(int i = 0; i < n; ++i) {

   if(S[v[i]].count(i) == 0) continue;

  int pos = i;

  ++ans;

  while (pos >= 0) {

     S[v[pos]].erase(pos);

     pos = find(pos, v[pos] - 1);

   }

  }

 

 printf("%d\n", ans);

 

 return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值