题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5200 ,数据离线处理。
这是BestCoder Round #36的C题,比赛时自己用线段树做,姿势不够优美,TLE了,后来才想到用离线处理的话很简单。
解法:
先把所有的树的高度和下标都存下来,然后按照高度进行排序;接下来把所有询问都先存下来,按照询问的高度进行排序。对于当前的查询h,在树中删除比h小的树木,假设删除的树的下标为p,则查看当前p+1和p-1位置的树木是否删去,如果两个位置都在,则+1,如果两个都被删去,则-1,如果一个存在一个已经被删去,段数不变。最后注意处理边界情况。
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <vector> #include <string> #include <string.h> #include <algorithm> using namespace std; #define LL __int64 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 50000 + 5; struct Tree { int h , pos; bool operator < (const Tree &tmp) const { return h < tmp.h; } }t[maxn] , q[maxn]; int vis[maxn] , ans[maxn]; int main() { int n , m , i , j; while(~scanf("%d %d" , &n , &m)) { for(i = 1 ; i <= n ; i++) { scanf("%d" , &t[i].h); t[i].pos = i; } for(i = 1 ; i <= m ; i++) { scanf("%d" , &q[i].h); q[i].pos = i; } sort(t + 1 , t + n + 1); sort(q + 1 , q + m + 1); memset(vis , 0 , sizeof(vis)); vis[0] = vis[n + 1] = 1; int cnt = 1; for(i = j = 1 ; i <= m ; i++) { while(j <= n && t[j].h <= q[i].h) { int p = t[j++].pos; if(vis[p - 1] && vis[p + 1]) cnt--; if(!vis[p - 1] && !vis[p + 1]) cnt++; vis[p] = 1; } ans[q[i].pos] = cnt; } for(i = 1 ; i <= m ; i++) printf("%d\n" , ans[i]); } return 0; }
时间: 2024-10-29 10:10:24