这题第一想法就是暴力,但是时间给了8s,卡的就是暴力。所以用线段树来做。
我自己没有想出来解法,后来研究了NotOnlySuccess的代码才恍然大悟,原来思想的魅力是这么大。然后自己写了自己的代码。至于线段树的风格嘛,我开始就是看他的代码,所以线段树这块现在都是他的风格,什么时候等我更透彻的对线段树有了深层次的认识的时候我应该就能开自己的关于线段树的代码风格了。
本题:将树上所有节点初始化为板子的宽度。然后每次读入一个宽度,判断这个宽度是不是比板子中余下的最大宽度要大。是的话输出-1,不是的话那必定有一个位置可以放这个通告。优先放到左子树里面,这是因为题目中要求能放到最高就放到最高。然后在安插的地方减去这个宽度,再更新线段树。还有在初始化树的时候,要注意判断h与n的关系,如果h大于n则将n值赋给h,否则会出现RE的,h的范围太大啦,而n的范围是200000.好了就这些了。 原型就是线段树找最大值-节点值的修改-更新。就这些。
1 #include <stdio.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 #define max(a,b) ((a)>(b)?(a):(b)) 5 #define maxn 880000 6 int MAX[maxn]; 7 int w; 8 void PushUp(int rt) 9 { 10 MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]); 11 return; 12 } 13 void build(int l,int r,int rt) 14 { 15 16 MAX[rt]=w; 17 if(l==r) 18 { 19 return; 20 } 21 int m=(l+r)>>1; 22 build(lson); 23 build(rson); 24 } 25 int query(int a,int l,int r,int rt) 26 { 27 if(r==l) 28 { 29 MAX[rt]-=a; 30 return l; 31 } 32 int m=(r+l)>>1; 33 int res=MAX[rt<<1]>=a?query(a,lson):query(a,rson); 34 PushUp(rt); 35 return res; 36 } 37 int main() 38 { 39 int h,x,n; 40 while(~scanf("%d%d%d",&h,&w,&n)) 41 { 42 if(h>n) 43 h=n; 44 build(1,h,1); 45 while(n--) 46 { 47 scanf("%d",&x); 48 if(x>MAX[1]) 49 printf("-1\n"); 50 else 51 printf("%d\n",query(x,1,h,1)); 52 } 53 } 54 return 0; 55 } 56 57