题目很好理解
我只写了两种一种是update和query合并的线段树是参考的。还有是分开的最开始写的
本来想写树状数组的但是一下子真没想到区间最值的更新位置怎么弄就先缓缓吧。。希望有大牛可以指点
#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 222222; int h , w , n; int MAX[maxn<<2]; void PushUP(int rt) { MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]); } void build(int l,int r,int rt) { MAX[rt] = w; if (l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); } void update(int x,int l,int r,int rt) { if (l == r) { MAX[rt] -= x; return ; } int m = (l + r) >> 1; (MAX[rt<<1] >= x) ? update(x , lson) : update(x , rson); PushUP(rt); } int query(int x,int l,int r,int rt) { if (l == r) { // MAX[rt] -= x; return l;//RETURN L } int m = (l + r) >> 1; //如果该段(根节点判断)可以存下X 那么就在左子树(本行) 反正就需要在下一行找 int ret = (MAX[rt<<1] >= x) ? query(x , lson) : query(x , rson); //PushUP(rt); return ret; } int main() { while (~scanf("%d%d%d",&h,&w,&n)) { if (h > n) h = n; build(1 , h , 1); //用高度建边,每一个高度有个W while (n --) { int x; scanf("%d",&x); if (MAX[1] < x) puts("-1"); else { printf("%d\n",query(x , 1 , h , 1)); //如果写updat需要写在query的后面因为先查到以后然后在将该值放进去并更新 update(x,1,h,1); } } } return 0; }
合并的参考的网上的
#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 222222; int h , w , n; int MAX[maxn<<2]; void PushUP(int rt) { MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]); } void build(int l,int r,int rt) { MAX[rt] = w; if (l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); } int query(int x,int l,int r,int rt) { if (l == r) { //其中每个高度有一个w值与其对应 MAX[rt] -= x; //以高度为线段建立,最后返回L的值代表当前高度 return l; } int m = (l + r) >> 1; //query在执行的同时将update的操作一并做了,这样比较简洁 int ret = (MAX[rt<<1] >= x) ? query(x , lson) : query(x , rson); PushUP(rt); return ret; } int main() { while (~scanf("%d%d%d",&h,&w,&n)) { if (h > n) h = n; build(1 , h , 1); while (n --) { int x; scanf("%d",&x); if (MAX[1] < x) puts("-1"); else printf("%d\n",query(x , 1 , h , 1)); } } return 0; }