线段树 区间合并

来源:互联网 发布:中科软件集团有限公司 编辑:程序博客网 时间:2024/05/17 02:18

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|1using 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|1using 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;}


原创粉丝点击