线段树典型例题--poj3667 hotel

来源:互联网 发布:怎么把淘宝店做起来 编辑:程序博客网 时间:2024/05/29 10:36

题目很像内存分配。

线段树维护这样几个量:

col:节点的颜色(0--没有覆盖,1--全覆盖,-1--有多种颜色)

dl:从左边开始的最长连续段

dr:从右边开始的最长连续段

dm:节点中的最长连续段

dp:节点中最长连续段的开始位置

具体见代码:

#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <algorithm>using namespace std;const int N=400000;int dl[N],dr[N],dm[N],dp[N],col[N],l[N],r[N];bool pp[N];int n,m;void build(int i,int ll,int rr){    l[i]=ll;r[i]=rr;    dl[i]=dr[i]=dm[i]=r[i]-l[i]+1;    col[i]=0;    dp[i]=l[i];    pp[i]=false;    if (l[i]==r[i]) return;    int mid=(l[i]+r[i])/2;    build(i*2,l[i],mid);    build(i*2+1,mid+1,r[i]);}void down(int i){    if (!pp[i]) return;    col[i*2]=col[i*2+1]=col[i];    if (col[i]==0)    {        dl[i*2]=dr[i*2]=dm[i*2]=r[i*2]-l[i*2]+1;        dp[i*2]=l[i*2];        dl[i*2+1]=dr[i*2+1]=dm[i*2+1]=r[i*2+1]-l[i*2+1]+1;        dp[i*2+1]=l[i*2+1];    }    else    {        dl[i*2]=dr[i*2]=dm[i*2]=0;        dl[i*2+1]=dr[i*2+1]=dm[i*2+1]=0;    }    pp[i]=false;    pp[i*2]=true;pp[i*2+1]=true;}int find(int i,int k){    if (l[i]==r[i])    {        if (dm[i]>=k) return dp[i];        else return 0;    }    if (dm[i]>=k)    {        down(i);        if (dm[i*2]>=k) return find(i*2,k);        else if (dr[i*2]+dl[i*2+1]>=k) return r[i*2]-dr[i*2]+1;        else if (dm[i*2+1]>=k) return find(i*2+1,k);    }    else return 0;}void update(int i){    if (col[i*2]==0 || col[i*2+1]==0)    {        if (col[i*2+1]==col[i*2]) col[i]=0;        else col[i]=-1;        if (col[i*2]==0) dl[i]=dl[i*2]+dl[i*2+1];        else dl[i]=dl[i*2];        if (col[i*2+1]==0) dr[i]=dr[i*2]+dr[i*2+1];        else dr[i]=dr[i*2+1];    }    else if (col[i*2]==-1 || col[i*2+1]==-1)    {        col[i]=-1;        dl[i]=dl[i*2];        dr[i]=dr[i*2+1];    }    else if (col[i*2]==1 && col[i*2+1]==1)    {        col[i]=1;        dl[i]=dr[i]=0;    }    dm[i]=dm[i*2];dp[i]=dp[i*2];    if (dr[i*2]+dl[i*2+1]>dm[i])    {        dm[i]=dr[i*2]+dl[i*2+1];        dp[i]=r[i*2]-dr[i*2]+1;    }    else if (dr[i*2]+dl[i*2+1]==dm[i] && r[i*2]-dr[i*2]+1<dp[i])        dp[i]=r[i*2]-dr[i*2]+1;    if (dm[i*2+1]>dm[i])    {        dm[i]=dm[i*2+1];        dp[i]=dp[i*2+1];    }    else if (dm[i*2+1]==dm[i] && dp[i*2+1]<dp[i])        dp[i]=dp[i*2+1];}void change(int i,int x,int y,int cc){    if (x<=l[i] && y>=r[i])    {        col[i]=cc;        if (col[i]==0)        {            dl[i]=dr[i]=dm[i]=r[i]-l[i]+1;            dp[i]=l[i];        }        else dl[i]=dr[i]=dm[i]=0;        pp[i]=true;        return;    }    down(i);    int mid=(l[i]+r[i])/2;    if (x<=mid) change(i*2,x,y,cc);    if (y>mid) change(i*2+1,x,y,cc);    update(i);}int main(){    int i,j,k,d;    freopen("in","r",stdin);    scanf("%d%d",&n,&m);    build(1,1,n);    for (i=1;i<=m;i++)    {        scanf("%d",&j);        if (j==1)        {            scanf("%d",&d);            k=find(1,d);            printf("%d\n",k);            if (k>0) change(1,k,k+d-1,1);        }        else        {            scanf("%d%d",&k,&d);            change(1,k,k+d-1,0);        }    }}


原创粉丝点击