线段树 区间合并

HDU 1540 Tunnel Warfare

这道题中我们用0表示该点是好的,1表示已经被毁坏。那么这道题就是更新点查找区间的线段树,但是为了能够求某个点连续的0的个数,我们在线段树内需要记一个区间左右端点连续的0的个数。这样当查询的时候,分成两边来查询,然后判断一下点本身是否为被毁坏就行了。

详细见代码:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <stack>
#define MAX 50010
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1

using namespace std;
typedef struct SEG
{
    int dt;
    int lnum,rnum;
}Seg;
Seg seg[MAX<<2];
void PushUp(int l,int r,int k)
{
    if(seg[k<<1].dt==seg[k<<1|1].dt)
        seg[k].dt=seg[k<<1].dt;
    else
        seg[k].dt=-1;

    int m = (l+r)>>1;
    if(seg[k<<1].lnum==(m-l+1))
        seg[k].lnum=seg[k<<1].lnum+seg[k<<1|1].lnum;
    else
        seg[k].lnum=seg[k<<1].lnum;

    if(seg[k<<1|1].rnum==(r-m))
        seg[k].rnum=seg[k<<1|1].rnum+seg[k<<1].rnum;
    else
        seg[k].rnum=seg[k<<1|1].rnum;

}
void PushDown(int l,int r,int k)
{
    if(seg[k].dt>-1)
    {
        int m = (l+r)>>1;
        seg[k<<1].dt=seg[k<<1|1].dt;
        if(seg[k].dt==0)
        {
            seg[k<<1].lnum=seg[k<<1].rnum=m-l+1;
            seg[k<<1|1].lnum=seg[k<<1|1].rnum=r-m;
        }
        else
        {
            seg[k<<1].lnum=seg[k<<1].rnum=0;
            seg[k<<1|1].lnum=seg[k<<1|1].rnum=0;
        }
        seg[k].dt=-1;
    }
}
void Init(int l,int r,int k)
{
    seg[k].dt=0;
    if(l==r)
    {
        seg[k].lnum=seg[k].rnum=1;
        return ;
    }
    int m = (l+r)>>1;
    Init(lson);
    Init(rson);
    PushUp(l,r,k);
}
void Update(int id,int v,int l,int r,int k)
{
    if(l==r&&l==id)
    {
        seg[k].dt=v;
        if(v==0)
            seg[k].lnum=seg[k].rnum=1;
        else
            seg[k].lnum=seg[k].rnum=0;

        return ;
    }
    PushDown(l,r,k);
    int m = (l+r)>>1;
    if(id<=m)
        Update(id,v,lson);
    else
        Update(id,v,rson);
    PushUp(l,r,k);
}
Seg Query(int ll,int rr,int l,int r,int k)
{
    if(ll>rr)
    {
        Seg ans ;
        ans.lnum=ans.rnum=0;
        return ans;
    }
    if(ll==l&&rr==r)
    {
        return seg[k];
    }
    PushDown(l,r,k);
    int m = (l+r)>>1;
    Seg ans;
    if(rr<=m)
        ans = Query(ll,rr,lson);
    else if(ll>m)
        ans = Query(ll,rr,rson);
    else
    {
        Seg a = Query(ll,m,lson);
        Seg b = Query(m+1,rr,rson);
        if(a.lnum==(m-ll+1))
            ans.lnum=a.lnum+b.lnum;
        else
            ans.lnum=a.lnum;
        if(b.rnum==(rr-m))
            ans.rnum=b.rnum+a.rnum;
        else
            ans.rnum=b.rnum;

    }
    PushUp(l,r,k);
    return ans;
}

stack <int> st;

int main()
{
    int n,m;
    char op[4];
    int a;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        while(!st.empty())
            st.pop();
        Init(1,n,1);
        while(m--)
        {
            scanf("%s",op);
            if(op[0]!='R')
                scanf("%d",&a);
            if(op[0]=='D')
            {
                st.push(a);
                Update(a,1,1,n,1);
            }
            else if(op[0]=='R')
            {
                int t = st.top();
                st.pop();
                Update(t,0,1,n,1);
            }
            else
            {
                Seg ans1 = Query(1,a-1,1,n,1);
                Seg ans2 = Query(a,n,1,n,1);
                if(ans2.lnum==0)
                    printf("0\n");
                else
                {
                    printf("%d\n",ans1.rnum+ans2.lnum);
                }
            }
        }
    }
    return 0;
}



HDU 2871 Memory Control

http://acm.hdu.edu.cn/showproblem.php?pid=2871

这道题其实就是维护一个区间连续的0的情况,这里包括将一个区间置为0或1,;然后就是对于一个块,有一个区间表示它所占用的内存单元,然后需要输出编号为idx的单元所在的块的起始标号和终止标号;还有一个就是查找第x个块的起始地址。

对于前面第一个要求,直接使用线段树进行维护,记法和Hotel是一样的。

对于其他的两个操作,我们已经很清楚的知道每一个块的左端点和右端点,维护一个左端点有序的队列,进行二分查找。也就是说没New一个块,那么我们就向有序列中添加一个块的左右断电的节点;没删除一个块,我们就将该点从序列中删除。

这道题有点猥琐,将一个块的左右端点放在线段树内维护要T,不知道是我写搓了还是本来就卡这个时限。

如果有不明白还是看看我的代码吧:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#define MAX 50100
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1
using namespace std;

typedef struct SEG
{
    int dt;
    int lnum,mnum,rnum;
}Seg;
Seg seg[MAX<<2];

void PushUp(int l,int r,int k)
{
    if(seg[k<<1].dt==seg[k<<1|1].dt)
        seg[k].dt=seg[k<<1].dt;
    else
        seg[k].dt=-1;
    int m = (l+r)>>1;
    if(seg[k<<1].lnum==(m-l+1))
        seg[k].lnum=seg[k<<1].lnum+seg[k<<1|1].lnum;
    else
        seg[k].lnum=seg[k<<1].lnum;

    if(seg[k<<1|1].rnum==(r-m))
        seg[k].rnum=seg[k<<1|1].rnum+seg[k<<1].rnum;
    else
        seg[k].rnum=seg[k<<1|1].rnum;

    seg[k].mnum=max(seg[k<<1].rnum+seg[k<<1|1].lnum,max(seg[k<<1].mnum,seg[k<<1|1].mnum));
    seg[k].mnum=max(seg[k].mnum,max(seg[k].lnum,seg[k].rnum));

}

void PushDown(int l,int r,int k)
{
    if(seg[k].dt>-1)
    {
        int m = (l+r)>>1;
        if(seg[k].dt==0)
        {
            seg[k<<1].dt=0;
            seg[k<<1].lnum=seg[k<<1].mnum=seg[k<<1].rnum=m-l+1;

            seg[k<<1|1].dt=0;
            seg[k<<1|1].lnum=seg[k<<1|1].mnum=seg[k<<1|1].rnum=r-m;
        }
        else
        {
            seg[k<<1].dt=seg[k<<1|1].dt=seg[k].dt;
            seg[k<<1].lnum=seg[k<<1].mnum=seg[k<<1].rnum=0;
            seg[k<<1|1].lnum=seg[k<<1|1].mnum=seg[k<<1|1].rnum=0;
        }
        seg[k].dt=-1;
    }
}

void Init(int l,int r,int k)
{
    seg[k].dt=0;
    if(l==r)
    {
        seg[k].lnum=seg[k].rnum=seg[k].mnum=1;
        return ;
    }
    int m = (l+r)>>1;
    Init(lson);
    Init(rson);
    PushUp(l,r,k);
}


void Update(int ll,int rr,int v,int l,int r,int k)
{
    if(ll==l&&rr==r)
    {
        seg[k].dt=v;
        if(v==0)
        {
            seg[k].lnum=seg[k].mnum=seg[k].rnum=r-l+1;
        }
        else
        {
            seg[k].lnum=seg[k].mnum=seg[k].rnum=0;
        }
        return ;
    }
    PushDown(l,r,k);
    int m = (l+r)>>1;
    if(rr<=m)
        Update(ll,rr,v,lson);
    else if(ll>m)
        Update(ll,rr,v,rson);
    else
    {
        Update(ll,m,v,lson);
        Update(m+1,rr,v,rson);
    }
    PushUp(l,r,k);
}
int Query(int x,int l,int r,int k)//查找连续的x个0
{
    if(seg[k].mnum<x)
        return 0;
    int m = (l+r)>>1;
    if(seg[k].lnum>=x)
        return l;
    PushDown(l,r,k);
    int ans;
    if(seg[k<<1].mnum>=x)
        ans = Query(x,lson);
    else if(seg[k<<1].rnum+seg[k<<1|1].lnum>=x)
        ans = m-seg[k<<1].rnum+1;
    else
        ans = Query(x,rson);
    PushUp(l,r,k);
    return ans;
}

typedef struct NODE
{
    int l,r;
}Node;
vector<Node> myList;

int Find(int x)
{
    int l = 0;
    int r = myList.size()-1;
    while(l<=r)
    {
        int mid = (l+r)>>1;
        if(x>=myList[mid].l)
            l = mid+1;
        else
            r = mid-1;
    }
    return l;
}

int main()
{
    int n,m;
    int a,b;
    char op[20];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        Init(1,n,1);
        myList.clear();
        while(m--)
        {
            scanf("%s",op);
            if(strcmp(op,"Reset")!=0)
                scanf("%d",&a);
            if(strcmp(op,"New")==0)
            {
                int ans = Query(a,1,n,1);
                if(ans==0)
                    printf("Reject New\n");
                else
                {
                    Update(ans,ans+a-1,1,1,n,1);
                    Node t ;
                    t.l=ans,t.r=ans+a-1;
                    int x = Find(t.l);
                    myList.insert(myList.begin()+x,t);
                    printf("New at %d\n",ans);
                }
            }
            else if(strcmp(op,"Free")==0)
            {
                int t = Find(a);
                --t;
                if(t>-1&&myList[t].r>=a)
                {
                    printf("Free from %d to %d\n",myList[t].l,myList[t].r);
                    Update(myList[t].l,myList[t].r,0,1,n,1);
                    myList.erase(myList.begin()+t);
                }
                else
                {
                    printf("Reject Free\n");
                }

            }
            else if(strcmp(op,"Get")==0)
            {
                int len = myList.size();
                --a;
                if(a>=len)
                    printf("Reject Get\n");
                else
                {
                    printf("Get at %d\n",myList[a].l);
                }
            }
            else
            {
                Update(1,n,0,1,n,1);
                myList.clear();
                printf("Reset Now\n");
            }
        }
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(struct,query)