题意:
有一个H*W的广告牌,当插入一个广告时(1*Wi),问最靠前的插入方式是什么
新生赛有个类似的题目,可惜当时居然没水过去。
果断用线段树做 以H为线段 建树,存[l,r]中最大的宽度,因为区间最大值满足区间和性质。
所以线段树几个要素如下:
线段:H
区间和性质:最大值
代码:
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 222222 using namespace std; int h,w,n; int tree[maxn*4]; int A[maxn]; void PushUp(int rt) { tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); } int build(int l,int r,int rt) { if(l==r) {tree[rt]=w;return 0;} int m=(l+r)>>1; build(lson); build(rson); PushUp(rt); } void input() { for(int i=1;i<=n;i++) scanf("%d",&A[i]); } int updata(int p,int k,int l,int r,int rt) { int m; if(l==r) {tree[rt]+=k;return 0;} m=(l+r)>>1; if(p<=m) updata(p,k,lson); else updata(p,k,rson); PushUp(rt); } int query(int p,int l,int r,int rt) { if(p>tree[rt]) return -1; if(l==r) return l; int m=(l+r)>>1; if(p<=tree[rt<<1]) return query(p,lson); else return query(p,rson); } void solve() { for(int i=1;i<=n;i++) { int t=query(A[i],1,h,1); printf("%d\n",t); if(t!=-1) { updata(t,-A[i],1,h,1); } } } void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int main() { // init(); while(scanf("%d%d%d",&h,&w,&n)!=EOF) { memset(tree,0,sizeof(tree)); h=min(h,200000); build(1,h,1); input(); solve(); } return 0; }