題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=2795php
hhanger大神的題目,水題都得有點思惟。ios
題意:h*w的木板,放進一些1*L的物品,求每次放空間能容納且最上邊的位子
思路:每次找到最大值的位子,而後減去L
線段樹功能:query:區間求最大值的位子(直接把update的操做在query裏作了)數組
技巧挺好,一開始本身思路建個超大二維數組,顯然內存不夠。ui
而後。 線段樹的話其實就是深搜,if(l==r) 返回的確定是最左邊的結點,哈~spa
判斷的時候直接用Max[1]與p比較就能判斷是否輸出-1,贊一個!!code
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r int h,w,n; const int maxn=200005;// 是200000仍是20000要搞清楚 int Max[maxn<<2]; //開maxn的多少倍結合最底層的結點數加以注意 void Pushup(int rt) { Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); } void build(int rt,int l,int r) { Max[rt]=w; if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); } int query(int p,int rt,int l,int r)//技巧5 . update放在query裏面了 { if(l==r) { Max[rt]-=p; return l;// 2. 返回行數 } int m=(l+r)>>1; int ret; ret=(Max[rt<<1]>=p)?query(p,lson):query(p,rson);// 技巧1.這地方深搜返回最左邊的結點即符合的。 Pushup(rt);// 技巧4 . 本身寫這個地方有可能會忘 return ret; } int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { if(h>n) {h=n;} build(1,1,h); int p; for(int i=1;i<=n;i++) { scanf("%d",&p); if(Max[1]<p) printf("-1\n"); // 技巧3.Max[1]最根結點必定是最大值 else { int ans=query(p,1,1,h); printf("%d\n",ans); } } } return 0; }