题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2795/
题目大意:有一块长方形木板,从上到下被分成h*w的区域,现要将n个长条放进这些区域中,要求从上到下只要后面空余位置够就放,紧贴最左侧放置。由于给出长度为C的长条之后只要一个区间[l,r]的最大值大于等于C我们就可以放置,所以考虑用线段树维护区间的最大值。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define dbg(args) cout<<#args<<":"<<args<<endl; 17 #define pb(i) push_back(i) 18 #define ppb(x) pop_back(x) 19 #define inf 0x3f3f3f3f 20 #define maxn 200005 21 int n,m,h,w; 22 int t[maxn<<2]; 23 void build(int l,int r,int rt) 24 { 25 if(l==r){ 26 t[rt]=w;//初始最大值都是栏的长度 27 return; 28 } 29 int mid =l+r>>1; 30 build(lson); 31 build(rson); 32 t[rt]=max(t[rt<<1],t[rt<<1|1]); 33 } 34 void update(int l,int r,int rt,int C) 35 { 36 if(l==r) 37 { 38 t[rt]-=C; 39 pf("%d ",l); 40 return; 41 } 42 int mid=l+r>>1; 43 if(C<=t[rt<<1]) update(lson,C);//优先往左子树走,保证最终放在一个区间最大值比C大的区间的最左端 44 else update(rson,C); 45 t[rt]=max(t[rt<<1],t[rt<<1|1]); 46 } 47 int main() 48 { 49 //freopen("input.txt","r",stdin); 50 //freopen("output.txt","w",stdout); 51 std::ios::sync_with_stdio(false); 52 while(scanf("%d%d%d",&h,&w,&n)==3) 53 { 54 if(h>n)h=n;//最多粘贴n行 55 build(1,h,1); 56 // dbg(t[1]); 57 int x; 58 while(n--) 59 { 60 scan(x); 61 if(x>t[1])pf("-1 ");//最大的位置容不下它 62 else update(1,h,1,x); 63 } 64 } 65 66 }