HDU_2871 线段树+vecor的中间插入和删除使用

本来这个题目就是个合并区间的题,就跟Hotel一样,要插入一段,则找左孩子 合并后的中间区间 右孩子,但是比较恶心的是,他需要实时得到某一段的起终点,或者某个点在第几个段里面,我想过在线段树里面加入几个变量来记录左右边界,发现还是不行,因为还要可以消除某个区间段

后来找博客发现向量原来还可以动态的插入和删除,那我把每一块的起终点放在向量里面,既能有序的进行查找,又能再Free操作的时候,直接马上把这个区间抹除,解决了这个问题,其他就跟Hotel区间查询 和 懒惰标记是一样的了,由于向量里面存储的是有序的,所以用二分进行查找

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 50010
using namespace std;
typedef pair<int,int> pill;
vector<pill> till;
int mc[N*3],lc[N*3],rc[N*3],flag[N*3];
int n,m;
int max(int a,int b) {return a>b? a:b;}
void up(int rt,int l,int r)
{
    int ll=rt<<1,rr=rt<<1|1;
    mc[rt]=max(mc[ll],mc[rr]);
    lc[rt]=lc[ll];rc[rt]=rc[rr];
    int mid=(l+r)>>1;
    if (lc[rt]==mid-l+1) lc[rt]+=lc[rr];
    if (rc[rt]==r-mid)   rc[rt]+=rc[ll];
    if (lc[rr]+rc[ll]>mc[rt]){
        mc[rt]=lc[rr]+rc[ll];
    }
}
void build(int rt,int l,int r)
{
    flag[rt]=-1;
    if (l>=r){
        mc[rt]=lc[rt]=rc[rt]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    up(rt,l,r);
}
void pushdown(int rt,int l,int r){
    if (flag[rt]==-1 || l>=r) return;
    int mid=(l+r)>>1;
    mc[rt<<1]=(mid-l+1)*flag[rt];
    mc[rt<<1|1]=(r-mid)*flag[rt];
    lc[rt<<1]=rc[rt<<1]=(mid-l+1)*flag[rt];
    lc[rt<<1|1]=rc[rt<<1|1]=(r-mid)*flag[rt];
    flag[rt<<1]=flag[rt<<1|1]=flag[rt];
    flag[rt]=-1;
}
void cover(int L,int R,int rt,int l,int r,int rec){
    int mid=(l+r)>>1;
    if (L<=l && r<=R){
        flag[rt]=rec;
        mc[rt]=lc[rt]=rc[rt]=(r-l+1)*flag[rt];
        return;
    }
    if (flag[rt]!=-1) pushdown(rt,l,r);
    if (L<=mid) cover(L,R,lson,rec);
    if (R>mid) cover(L,R,rson,rec);
    up(rt,l,r);
}
int query(int x,int rt,int l,int r)
{
    pushdown(rt,l,r);
    if (l>=r) return l;
    int mid=(l+r)>>1;
    if (mc[rt<<1]>=x) return query(x,lson);
    if (lc[rt<<1|1]+rc[rt<<1]>=x) return mid-rc[rt<<1]+1;
    return query(x,rson);
}
int bs(int x)
{
    int l=0,r=till.size()-1,mid;
    while (l<=r){
        mid=(l+r)>>1;
        if (till[mid].first<=x) l=mid+1;
        else r=mid-1;
    }
    return l;
}
void solve(char* ch)
{
    if (ch[0]=='R'){
            till.clear();
            cover(1,n,1,1,n,1);
            puts("Reset Now");
            return;
    }
    int d;
    scanf("%d",&d);
    if (ch[0]=='N'){
             if (mc[1]<d) {puts("Reject New");return;}
            int sta=query(d,1,1,n);
            printf("New at %d\n",sta);
            int a=bs(sta);
            pill c;c.first=sta;c.second=sta+d-1;
            till.insert(till.begin()+a,c);
            cover(sta,sta+d-1,1,1,n,0);
            return;
    }
    if (ch[0]=='F'){
        int id=bs(d);
        id--;
        if (id<=-1||till[id].second<d) puts("Reject Free");
        else{
            printf("Free from %d to %d\n",till[id].first,till[id].second);
            cover(till[id].first,till[id].second,1,1,n,1);
            till.erase(till.begin()+id);
        }
        return;
    }
    if (ch[0]=='G')
    {
        if (d > till.size())
            printf("Reject Get\n");
         else printf("Get at %d\n", till[d-1].first);
    }
}
int main()
{
    char ch[8];
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,1,n);
        till.clear();
        for (int q=0;q<m;q++){
         scanf("%s",ch);
         solve(ch);
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2014-05-09 10:02  KRisen  阅读(317)  评论(0编辑  收藏  举报