题意:有一块板,规格为h*w,然后有n张海报,每张海报的规格为1*wi,选择贴海报的位置是:尽量高,同一高度,选择尽量靠左的地方。要求输出每张海报的高度位置。
因为最多只有二十万张海报,所以板的最大的长度不会超过二十万,但是要小心,如果板的长度小于h,我们还要用h来建树。起初在查询的时候并不直接去更新它,而是查询找出它的更新位置的后,再写个updata函数去更新,但是我们可以在查询到它的位置的时候,同时去更新当前点的剩余长度,然后回溯更新所有祖先区间。返回它的查询位置的时候,因为左儿子找到的位置是pos1,右儿子找到的位置是pos2,两者都赋初值为0,又因为每次查询只找出一个位置,也就是说pos1和pos2中只有一个被改变,另一个仍保持0,所以返回pos1+pos2是正确的。
/*代码风格更新后*/ #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=200005; struct node { int lft,rht,mx; int mid(){return MID(lft,rht);} }; int h,w,n; struct Segtree { node tree[N*4]; void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].mx=w; if(lft!=rht) { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } int updata(int valu,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(lft==rht) { tree[ind].mx-=valu; return lft; } else { int pos; if(tree[LL(ind)].mx>=valu) pos=updata(valu,LL(ind)); else pos=updata(valu,RR(ind)); tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx); return pos; } } }seg; int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { int tmp; seg.build(1,min(N,h),1); for(int i=0;i<n;i++) { scanf("%d",&tmp); if(seg.tree[1].mx<tmp) puts("-1"); else printf("%d\n",seg.updata(tmp,1)); } } return 0; }
/*代码风格更新前*/ #include <iostream> #include <cstdio> using namespace std; const int N=200005; int h,w,n; struct node { int left,right,len; int mid(){return left+(right-left)/2;} }; struct Segtree { node tree[N*4]; void build(int left,int right,int r) { tree[r].left=left; tree[r].right=right; tree[r].len=w; if(left<right) { int mid=tree[r].mid(); build(left,mid,r*2); build(mid+1,right,r*2+1); } } int query(int len,int r) { if(tree[r].left==tree[r].right) { tree[r].len-=len; return tree[r].left; } else { int pos1=0,pos2=0; if(len<=tree[r*2].len) pos1=query(len,r*2); else if(len<=tree[r*2+1].len) pos2=query(len,r*2+1); tree[r].len=max(tree[r*2].len,tree[r*2+1].len); return pos1+pos2; } } }seg; int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { seg.build(1,min(200000,h),1); for(int i=0;i<n;i++) { int len; scanf("%d",&len); if(seg.tree[1].len>=len) printf("%d\n",seg.query(len,1)); else puts("-1"); } } return 0; }