hdu 2795 Billboard 线段树基础题

#include <stdio.h>
#include <string.h>
#define maxn 200000
struct node{
    int l,r,id,w;
}e[maxn*4];
int h,w,n;
void build(int a,int b,int c)
{
    e[c].l=a;
    e[c].r=b;
    e[c].id=a;
    e[c].w=w;
    if(a==b)
        return ;
    int mid=(a+b)/2;
    build(a,mid,2*c);
    build(mid+1,b,2*c+1);
}
int query(int val,int c)
{
    //printf("%d %d %d %d\n",e[c].l,e[c].r,e[c].w,val);
    if(e[c].w<val)
        return -1;
    //printf("***\n");
    if(e[c].l==e[c].r)
        return e[c].id;

    if(e[2*c].w>=val)
        return query(val,2*c);
    else
        return query(val,2*c+1);
}
void update(int a,int b,int c,int val)
{
    if(e[c].l==a&&e[c].r==b)
    {
        e[c].w-=val;
        return;
    }
    int mid=(e[c].l+e[c].r)/2;
    if(b<=mid)
        update(a,b,2*c,val);
    else if(a>mid)
        update(a,b,2*c+1,val);
    if(e[2*c].w>e[2*c+1].w)
    {
        e[c].w=e[2*c].w;
        e[c].id=e[2*c].id;
    }
    else
    {
        e[c].w=e[2*c+1].w;
        e[c].id=e[2*c+1].id;
    }
}
int main()
{
    while(scanf("%d%d%d",&h,&w,&n)!=EOF)
    {
        int i,j,k;
        if(h>n)
            h=n;
        build(1,h,1);
        for(i=0;i<n;i++)
        {
            scanf("%d",&k);
            int t;
            t=query(k,1);
            printf("%d\n",t);
            if(t!=-1)
            update(t,t,1,k);
        }
    }
    return 0;
}
/*
以高度和广告数的较小值建线段树,树中w表示该段中最大空余量,id表示最大空余量所在行,从上还是记。每次贴广告
比较空余量,从上到下,有空余就贴。再根据查找到的空余行进行点更新。
*/

你可能感兴趣的:(线段树)