题目描述
为了在农场的一块土地上种奶牛吃的草,Farmer John必须要把前面的N棵树砍掉,这些树紧密地排成一条直线,并且用1-N编号标识,每一棵树都有自己的高度Hi(1≤Hi≤10000)。
Farmer John想用炸弹来摧毁这些树,这种炸弹除了能摧毁安装了炸弹的那棵树以外还能传递压倒两边矮于这一棵树的所有邻近树,直到遇到一棵不低于这一棵树的树为止。
例如:一排树的高度如下:1 2 5 4 3 3 6 6 2,如果Farmer John在第三棵树上装炸弹(高度为5),那么第二棵树也同样给压倒(高度为2<5),第一棵树也同样倒下(高度为1<2),再来看另一边第四棵树(高度为4<5)和第五棵树(高度为3<4)同样也给压倒。剩下的状态为:× × × × × 3 6 6 2,接下来在第七和第八棵树上安装炸弹就可以把剩下的树毁掉。
请你帮助Farmer John利用最少的炸弹把这些树毁掉。
输入格式
第一行,一个整数N(1≤N≤50000);
第二行至第N+1行,包含各棵树的高度Hi。
输出格式
第一至第?行,每一行为一个整数,代表安装炸弹的树的编号,按照升序输出。
输入样例
9
1
2
5
4
3
3
6
6
2
输出样例
3
7
8
题解
容易想到,从最高的树开始炸即可。


#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #define MAXN 50001 using namespace std; int n; int a[MAXN]; struct node { int hei; int idx; }b[MAXN]; bool cmp(node a, node b) { return a.hei > b.hei;// 从高的树开始炸 } priority_queue<int, vector<int>, greater<int> > q;// 答案从小到大排序 int main() { scanf("%d", &n); for(register int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i].hei = a[i]; b[i].idx = i; } sort(b + 1, b + 1 + n, cmp); for(register int i = 1, c; i <= n; i++) { if(a[b[i].idx]) { c = a[b[i].idx]; for(register int j = b[i].idx - 1; j >= 1; j--) {// 压到左边的数 if(a[j] < c) { if(a[j]) { c = a[j]; a[j] = 0; } else break; } else break; } c = a[b[i].idx]; for(register int j = b[i].idx + 1; j <= n; j++) {//压倒右边的数 if(a[j] < c) { if(a[j]) { c = a[j]; a[j] = 0; } else break; } else break; } q.push(b[i].idx); a[b[i].idx] = 0; } } while(!q.empty()) { printf("%d", q.top()); q.pop(); if(!q.empty()) putchar('\n'); } return 0; }