题意:高为 h,宽为 w 的广告板,往上面贴一些宽都是 1 的广告。要求尽量往上和往左贴,输入能贴在第几行,如果都贴不上输出-1.
首先取 min(h,n)作为线段树长度,因为最坏情况是 n 个广告每个一行,如果 h>n 的话剩下的肯定贴不了。
用线段树来维护 1~h 中剩余长度的最大值,利用其由上而下搜索和先遍历左子树的特性,找到广告板上最上面符合条件的行数。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn = 200005; int tree[maxn<<2]; int h, w, n; void pushUp(int rt){ tree[rt] = max(tree[rt<<1], tree[rt<<1|1]); } void build(int l, int r, int rt){ if(l == r){ tree[rt] = w; return; } int m = l+(r-l)/2; build(lson); build(rson); pushUp(rt); } int query(int num, int l, int r, int rt){ if(l == r){ tree[rt] -= num; return l; } int ans; int m = l+(r-l)/2; if(tree[rt<<1] >= num) ans = query(num, lson); else ans = query(num, rson); pushUp(rt); //更新 return ans; } int main(){ //freopen("a.txt", "r", stdin); while(~scanf("%d %d %d", &h, &w, &n)){ h = min(h, n); build(1, h, 1); for(int i = 0; i < n; i++){ int a; scanf("%d", &a); if(tree[1] < a) cout << "-1" << endl; else{ cout << query(a, 1, h, 1) << endl; } } } return 0; }