Hdu 5200 Trees (离线线段树)

来源:互联网 发布:mac电脑远程控制 编辑:程序博客网 时间:2024/04/26 18:04

题目大意:

校门外栽满了不同高度的树,每一次询问是 如果砍掉所有高度不超过q的树,那么还有多少个连续的块。


思路分析:

记录左连续和   右连续和  用来维护区间的连续块的数量。

seg[num] = seg[num<<1]+seg[num<<1|1] ;

如果中间部分连起来  那么减一即可。


#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define maxn 50005#define lson num<<1,s,mid#define rson num<<1|1,mid+1,e#define mid ((s+e)>>1)using namespace std;int lsum[maxn<<2],rsum[maxn<<2],seg[maxn<<2];struct tree{int height;int pos;bool operator < (const tree &cmp)const{return height<cmp.height;}}save[maxn];struct Ans{int index;int query;int ans;bool operator < (const Ans & cmp)const{return query<cmp.query;}}prt[maxn];bool cmp_id(Ans a,Ans b){return a.index<b.index;}void pushup(int num,int s,int e){lsum[num]=lsum[num<<1];if(lsum[num]==mid-s+1)lsum[num]+=lsum[num<<1|1];rsum[num]=rsum[num<<1|1];if(rsum[num]==e-mid)rsum[num]+=rsum[num<<1];seg[num]=seg[num<<1]+seg[num<<1|1];if(rsum[num<<1] && lsum[num<<1|1])seg[num]--;}void build(int num,int s,int e){if(s==e){lsum[num]=rsum[num]=seg[num]=1;return;}build(lson);build(rson);pushup(num,s,e);}void update(int num,int s,int e,int pos){if(s==e){lsum[num]--,rsum[num]--,seg[num]--;return;}if(pos<=mid)update(lson,pos);else update(rson,pos);pushup(num,s,e);}int main(){int n,q;while(scanf("%d%d",&n,&q)!=EOF){for(int i=1;i<=n;i++){scanf("%d",&save[i].height);save[i].pos=i;}sort(save+1,save+1+n);for(int i=1;i<=q;i++){scanf("%d",&prt[i].query);prt[i].index=i;}sort(prt+1,prt+1+q);build(1,1,n);int dex = 1;for(int i=1;i<=q;i++){while(save[dex].height<=prt[i].query && dex<=n){update(1,1,n,save[dex].pos);dex++;}prt[i].ans = seg[1];}sort(prt+1,prt+1+q,cmp_id);for(int i=1;i<=q;i++){printf("%d\n",prt[i].ans);}}return 0;}


0 0