标签:
题目大意:
校门外栽满了不同高度的树,每一次询问是 如果砍掉所有高度不超过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; }
标签:
原文地址:http://blog.csdn.net/u010709592/article/details/44965195