9-4(线段树最大值定位,区间合并)

来源:互联网 发布:java开发百度云播放器 编辑:程序博客网 时间:2024/06/08 08:18

hdu2795 Billboard
题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子
思路:每次找到最大值的位子,然后减去L
线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了)

#include <bits/stdc++.h>using namespace std;const int maxn = 200010;struct Tree{    int h, maxn;    int l, r;}tree[maxn*4];int h, w, n;void build(int node, int c){    tree[node].maxn = c;    if(tree[node].l == tree[node].r){        tree[node].h = tree[node].l;        return ;    }    int mid = (tree[node].l + tree[node].r)/2;    tree[node*2].l = tree[node].l;    tree[node*2].r = mid;    tree[node*2+1].l = mid+1;    tree[node*2+1].r = tree[node].r;    build(node*2, c);    build(node*2+1, c);}int query(int node, int c){    if(tree[node].l == tree[node].r){        tree[node].maxn -= c;        return tree[node].h;    }    int ans;    if(tree[node*2].maxn >= c)        ans = query(node*2, c);    else        ans = query(node*2+1, c);    tree[node].maxn = max(tree[node*2].maxn, tree[node*2+1].maxn);    return ans;}int main(){    while(~scanf("%d%d%d", &h, &w, &n)){        if(h > n) h = n;        tree[1].l = 1, tree[1].r = h;        build(1, w);        for(int i = 0; i < n; i++){            int wh;            scanf("%d", &wh);            if(tree[1].maxn>=wh)                printf("%d\n", query(1, wh));            else                printf("-1\n");        }    }    return 0;}

这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并
poj3667 Hotel
题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间
线段树操作:update:区间替换 query:询问满足条件的最左断点

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>using namespace std;const int maxn = 50010;#define lson node*2#define rson node*2+1struct Tree{    int l, r, c;    int maxn, lmaxn, rmaxn;}tree[5*maxn];int n, m;void pushdown(int node){    if(tree[node].c != -1){        tree[lson].c = tree[rson].c = tree[node].c;        if(tree[node].c == 1){            tree[lson].maxn = tree[lson].lmaxn = tree[lson].rmaxn = 0;            tree[rson].maxn = tree[rson].lmaxn = tree[rson].rmaxn = 0;        }        else{            int mid = (tree[node].r + tree[node].l)/2;            tree[lson].lmaxn = tree[lson].rmaxn = tree[lson].maxn = mid - tree[node].l +1;            tree[rson].lmaxn = tree[rson].rmaxn = tree[rson].maxn = tree[node].r - mid;        }        tree[node].c = -1;    }}void build(int node){    tree[node].c = -1;    tree[node].maxn = tree[node].lmaxn = tree[node].rmaxn = tree[node].r - tree[node].l +1;    if(tree[node].l == tree[node].r) return;    int mid = (tree[node].l + tree[node].r) /2;    tree[lson].l = tree[node].l;    tree[lson].r = mid;    tree[rson].l = mid+1;    tree[rson].r = tree[node].r;    build(lson);    build(rson);}void pushup(int node){    if(tree[lson].lmaxn == tree[lson].r - tree[lson].l +1)        tree[node].lmaxn = tree[lson].lmaxn + tree[rson].lmaxn;    else        tree[node].lmaxn = tree[lson].lmaxn;    if(tree[rson].rmaxn == tree[rson].r - tree[rson].l +1)        tree[node].rmaxn = tree[rson].rmaxn + tree[lson].rmaxn;    else        tree[node].rmaxn = tree[rson].rmaxn;    tree[node].maxn = max(tree[lson].rmaxn+tree[rson].lmaxn, max(tree[lson].maxn, tree[rson].maxn));  //注意是左右子树的最大值……}int query(int node, int dist){    if(tree[node].l == tree[node].r)         return tree[node].l;    pushdown(node);    if(tree[lson].maxn>=dist)        return query(lson, dist);    else if(tree[lson].rmaxn + tree[rson].lmaxn >= dist)        return (tree[node].r + tree[node].l) / 2 - tree[lson].rmaxn + 1;    else        return query(rson, dist);}void update(int node, int s, int e, int c){    if(s <= tree[node].l && tree[node].r <= e){        if(tree[node].l != tree[node].r) pushdown(node);        tree[node].c = c;        if(c == 0)            tree[node].lmaxn = tree[node].rmaxn = tree[node].maxn = tree[node].r - tree[node].l +1;        else            tree[node].lmaxn = tree[node].rmaxn = tree[node].maxn = 0;        return;    }    pushdown(node);    int mid = (tree[node].l + tree[node].r)/2;    if(s <= mid)        update(lson, s, e, c);    if(e > mid)        update(rson, s, e, c);    pushup(node);    return;}int main(){    //freopen("1.txt", "r", stdin);    scanf("%d%d", &n, &m);{        tree[1].l = 1, tree[1].r = n;        build(1);        for(int i = 0; i < m; i++){            int op;            scanf("%d", &op);            if(op == 1){                int dist;                 scanf("%d", &dist);                if(tree[1].maxn < dist){                    printf("0\n");                     continue;                }                int ans = query(1, dist);                printf("%d\n", ans);                update(1, ans, ans+dist-1, 1);            }            else{                int a, b;                scanf("%d%d", &a, &b);                update(1, a, a+b-1, 0);            }        }    }    return 0;}
原创粉丝点击