您的位置:首页 > 其它

hdu 2795 Billboard 线段树单点更新(线段树+二分)

2014-08-13 15:15 423 查看
机房网络好了,现在把博文补上。

这道题的模型是:求一个线段上大于等于某个值v的最小位置,并且把该位置的值减v。

用线段树维护区间上的最大值,若最大值大于等于v,则该位置在这个区间内,否则不在。用二分找出满足条件的最小位置。查询操作和修改操作一起完成。
//3140MS	4240K
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define lch(x) ((x)<<1)
#define rch(x) ((x)<<1 | 1)

using namespace std;

const int MAX_N = 200000;
int Max[MAX_N<<2];
int wi[MAX_N+5];
int h, w, n;

void build(){
for(int i=0; i<h<<2; i++)
Max[i] = w;
}

inline void push_up(int n){
Max
= max(Max[lch(n)], Max[rch(n)]);
}

int modify(int w, int n, int l, int r){
if(l == r){
Max
-= w;
return l;
}
int mid = (l+r)>>1;
int res = (Max[lch(n)] >= w) ? modify(w, lch(n), l, mid) : modify(w, rch(n), mid+1, r);
push_up(n);
return res;
}

int main(){
while(~scanf("%d%d%d", &h, &w, &n)){
if(h > n) h = n;
build();
for(int i=1; i<=n; i++){
scanf("%d", &wi[i]);
if(Max[1] < wi[i]) printf("-1\n");
else printf("%d\n", modify(wi[i], 1, 1, h));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: