hdu 2795 Billboard

    技术2022-05-20  45

    这道题把样例画一画之后,很直观的方法就是把高度映射到一维线段树上,每个叶子节点代表一列,然后一个值表示该列剩余的宽度,然后每个区间统计该区间的最大余量

     

    但问题是,h<=10^9,怎么办?注意到n<=200,000,我们插入n张海报,最多用到n列,也就是说,实际有效高度最多为n,于是,我们取

    h=min(h,n),这下h不会超过200,000,就可以以高度建树了,剩下的事情就简单了

     

    代码:

    #include<iostream> #include<memory.h> #include<string> #include<cstdio> #include<algorithm> #include<math.h> #include<stack> #include<queue> using namespace std; const int MAX=200005; struct node { int l,r,val,row; }t[MAX*5]; int n,h,w,ans; void build(int ll,int rr,int n) { t[n].l=ll; t[n].r=rr; if(ll==rr) { t[n].val=w; t[n].row=ll; return; } int mid=(ll+rr)/2; build(ll,mid,n*2); build(mid+1,rr,n*2+1); t[n].val=max(t[n*2].val,t[n*2+1].val); //t[n].row=0; } void update(int ll,int rr,int n,int x) { if(t[n].l==ll&&t[n].r==rr) { t[n].val-=x; return; } int mid=(t[n].l+t[n].r)/2; if(mid>=rr) update(ll,rr,n*2,x); else if(mid<ll) update(ll,rr,n*2+1,x); else { update(ll,mid,n*2,x); update(mid+1,rr,n*2+1,x); } t[n].val=max(t[n*2].val,t[n*2+1].val); } int query(int n,int x) { if(t[n].val<x) { return -1; } if(t[n].l==t[n].r) { return t[n].row; } if(t[n*2].val>=x) return query(n*2,x); else return query(n*2+1,x); } int main() { int i,j; while(scanf("%d%d%d",&h,&w,&n)!=EOF) { h=h<n?h:n; build(1,h,1); for(i=1;i<=n;i++) { scanf("%d",&j); int res=query(1,j); if(res!=-1) update(res,res,1,j); printf("%d/n",res); //cout<<t[1].val<<endl; } } return 0; } 


    最新回复(0)