//9372104 NKHelloWorld 3667 Accepted 3740K 1000MS G++ 3738B 2011-09-29 15:06:22
//9372139 NKHelloWorld 3667 Accepted 3228K 594MS C++ 3740B 2011-09-29 15:12:45
/*
转自:http://www.cnblogs.com/superbin/archive/2010/07/18/1780194.html
题型:线段树(设计并维护复杂域)
描述:旅店登记,1.找一段最靠前的连续w个空房间;2.退订[x,x-d+1]段的房间。
思路:
1. 域的设计
struct Seg {
    int l, r;
    int lx, rx, mx;
    char cv;
};
lx :左端连续空房间数
rx: 右端连续空房间数
mx: 连续最大空房间数
cv : = 0,全空, = 1 全满, = -1 非空非满。
2. 域的维护
开房:先用find(w, 1); 找到位置 rom, 然后用 mody(rom, rom+w-1, 0, 1); 进行插入操作
退房:进行删除操作mody(x, x-d+1, 1, 1)
因为此题区间的修改(插入和删除)很相似,所以用一个函数实现,0表示插入,1表示删除。
对cv域的维护包括   1. t[k].l == l && t[k].r == r 。 2. 根据父节点的cv值对子节点的修改(关键),find()和mody()中都需要有。
lx, rx, mx需要在回溯的过程维护:mx 为 两个子节点的mx和交叉区间和的最大值,
父节点的lx = 左子节点的lx + (右子节点的lx);
父节点的rx = 右子节点的rx + (左子节点的rx);
当左右子节点的lx,rx为整个区间长时,()需加上。
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 50010
struct SEGMENTTREE
{
    int lt,rt,lval,rval,totval,state;
}tree[4*MAXN];
int n,m;
void buildsegtree(int root,int lt,int rt)
{
    tree[root].lt = lt; tree[root].rt = rt;
    tree[root].lval = tree[root].rval = tree[root].totval = rt - lt + 1;
    tree[root].state = 0;
    if(lt != rt)
    {
        int mid = (lt+rt)>>1;
        buildsegtree(root<<1,lt,mid);
        buildsegtree(root<<1|1,mid+1,rt);
    }
}
void pushdown(int root)
{
    tree[root<<1].state = tree[root<<1|1].state = tree[root].state;
    if(tree[root].state == 0)
    {
        tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = tree[root<<1].rt - tree[root<<1].lt + 1;
        tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = tree[root<<1|1].rt - tree[root<<1|1].lt +1;
    }
    else
    {
        tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = 0;
        tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = 0;
    }
    tree[root].state = -1;
}
int query(int root,int lenth)
{
    if(tree[root].lt == tree[root].rt)
    {
        if(tree[root].state == false && lenth == 1)
            return tree[root].lt;
        return 0;
    }
    if(tree[root].state != -1)
        pushdown(root);
    if(tree[root<<1].totval >= lenth)
        return query(root<<1,lenth);
    if(tree[root<<1].rval + tree[root<<1|1].lval >= lenth)
        return tree[root<<1].rt - tree[root<<1].rval + 1;
    if(tree[root<<1|1].totval >= lenth)
        return query(root<<1|1,lenth);
    return 0;
}

void update(int root,int lt,int rt,int state)
{
    //printf("root:%d lt:%d rt:%d state:%d\n",root,lt,rt,state);
    if(tree[root].lt == lt && tree[root].rt == rt)
    {
        tree[root].state = state;
        if(state==1)
            tree[root].lval = tree[root].rval = tree[root].totval = 0;
        else if(state == 0)
            tree[root].lval = tree[root].rval = tree[root].totval = rt - lt+ 1;
        return ;
    }
    if(tree[root].state != -1)
        pushdown(root);
    int mid = (tree[root].lt + tree[root].rt)>>1;
    if( rt <= mid )
        update(root<<1,lt,rt,state);
    else if(lt > mid)
        update(root<<1|1,lt,rt,state);
    else
    {
        update(root<<1,lt,mid,state);
        update(root<<1|1,mid+1,rt,state);
    }
    tree[root].lval = tree[root<<1].lval;
    tree[root].rval = tree[root<<1|1].rval;
    tree[root].totval = max( max(tree[root<<1].totval,tree[root<<1|1].totval) , tree[root<<1].rval + tree[root<<1|1].lval);
    if(tree[root].lval == tree[root<<1].rt - tree[root<<1].lt + 1)
        tree[root].lval += tree[root<<1|1].lval;
    if(tree[root].rval == tree[root<<1|1].rt - tree[root<<1|1].lt +1)
        tree[root].rval += tree[root<<1].rval;
    if(tree[root<<1].state == tree[root<<1|1].state)
        tree[root].state = tree[root<<1].state;
}

void output(int root)
{
    printf("root: %d, lt:%d rt:%d\t lval:%d rval:%d totval:%d state:%d\n",root,tree[root].lt,tree[root].rt,tree[root].lval,tree[root].rval,tree[root].totval,tree[root].state);
    if(tree[root].lt != tree[root].rt)
    {
        output(root<<1);
        output(root<<1|1);
    }
}

int main()
{
    int i,a,b,op;
    scanf("%d%d",&n,&m);
    buildsegtree(1,1,n);
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&a);
            b = query(1,a);
            printf("%d\n",b);
            if(b)
            {
                update(1,b,b+a-1,1);
                //output(1);
            }
        }
        else
        {
            scanf("%d%d",&a,&b);
            update(1,a,a+b-1,0);
            //output(1);
        }
    }
    return 0;
}

posted on 2011-09-29 15:40  NKHe!!oWor!d  阅读(331)  评论(0编辑  收藏  举报