線段樹 區間合并

來源:互聯網
上載者:User

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,不知道是我寫搓了還是本來就卡這個時限。

如果有不明白還是看看My Code吧:

#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;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.