【HDU 2871 Memory Control】线段树之区间操作

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871

题目大意:

 四个操作:

1、New x     找一段长为x的空区间段填满。  下面用0表示空单元,1表示非空单元。

2、Free x  释放包含x的区间段

3、 Get x 找到第x个区间段

4、将整个区间都置为空。

解题思路:

     可以说这题应该算是线段树之区间操作里面比较好的经典题了。要注意的地方很多。对vector容器的用法又了解了很多。赞一个

View Code
  1 #include <cstdio>
  2 #include <vector>
  3 #include <iostream>
  4 using namespace std;
  5 
  6 #define  lz  2*u,l,mid
  7 #define  rz  2*u+1,mid+1,r
  8 const int maxn=50005;
  9 int flag[4*maxn];
 10 
 11 struct segment
 12 {
 13     int lm; // 从区间左端点开始的连续0个数;
 14     int rm; // 以区间右端点结束的连续0个数;
 15     int sm; // 整个区间最长连续的0个数;
 16 } tree[4*maxn];
 17 
 18 struct node
 19 {
 20     int s, d;
 21 };
 22 node tmp;
 23 vector<node>vt;
 24 
 25 void push_up(int u, int l, int r)
 26 {
 27     int mid= (l+r)>>1;
 28     tree[u].lm= tree[u*2].lm;
 29     tree[u].rm= tree[u*2+1].rm;
 30     tree[u].sm= max( tree[u*2].sm, tree[u*2+1].sm );
 31     if( tree[u*2].lm == mid-l+1 ) tree[u].lm += tree[u*2+1].lm;
 32     if( tree[u*2+1].rm == r-mid ) tree[u].rm += tree[u*2].rm;
 33     int t= tree[u*2].rm + tree[u*2+1].lm;
 34     if( t > tree[u].sm )  tree[u].sm= t;
 35 }
 36 
 37 void push_down(int u, int l, int r)
 38 {
 39     if(flag[u]>=0)
 40     {
 41         int mid=(l+r)>>1;
 42         flag[2*u]=flag[2*u+1]=flag[u];
 43         tree[2*u].lm= tree[2*u].rm= tree[2*u].sm= flag[u]?0:mid-l+1;
 44         tree[2*u+1].lm= tree[2*u+1].rm= tree[2*u+1].sm= flag[u]?0:r-mid;
 45         flag[u]=-1;
 46     }
 47 }
 48 
 49 void build(int u, int l, int r)
 50 {
 51     flag[u]=-1;
 52     if(l==r)
 53     {
 54         tree[u].lm= tree[u].rm= tree[u].sm= 1;
 55         return;
 56     }
 57     int mid= (l+r)>>1;
 58     build(lz);
 59     build(rz);
 60     push_up(u, l, r);
 61 }
 62 
 63 void Update(int u, int l, int r, int tl, int tr, int c)
 64 {
 65     if(tl<=l&&r<=tr)
 66     {
 67         tree[u].lm=tree[u].rm=tree[u].sm=c?0:r-l+1;
 68         flag[u]=c;
 69         return ;
 70     }
 71     push_down(u,l,r);
 72     int mid=(l+r)>>1;
 73     if(tr<=mid) Update(lz,tl,tr,c);
 74     else if(tl>mid) Update(rz,tl,tr,c);
 75     else
 76     {
 77         Update(lz,tl,mid,c);
 78         Update(rz,mid+1,tr,c);
 79     }
 80     push_up(u,l,r);
 81 }
 82 
 83 int  Query(int u, int l, int r, int p)
 84 {
 85     if(tree[u].sm==p&&r-l+1==p)   ///不仅要tree[u].sm==p而且要整个区间都被0覆盖,否则会出错
 86     {
 87         return l;
 88     }
 89     push_down(u,l,r);
 90     int mid= (l+r)>>1, t;
 91     if(p<=tree[2*u].sm)  return Query(lz,p);
 92     else if(tree[2*u].rm+tree[2*u+1].lm>=p) return mid-tree[2*u].rm+1;
 93     else return Query(rz,p);
 94 }
 95 
 96 int find(int tp)    ///二分查找
 97 {
 98     int l=0, r=vt.size()-1, mid, ans=-1;
 99     while(l<=r)
100     {
101         int mid=(l+r)>>1;
102         if(vt[mid].s<=tp)
103         {
104             ans=mid;
105             l=mid+1;
106         }
107         else r=mid-1;
108     }
109     return ans;
110 }
111 
112 int main()
113 {
114     int n, m;
115     while(cin >> n >> m)
116     {
117         build(1,1,n);
118         vt.clear();
119         while(m--)
120         {
121             char ch[6];
122             scanf("%s",ch);
123             if(ch[0]=='R')
124             {
125                 vt.clear();
126                 Update(1,1,n,1,n,0);
127                 puts("Reset Now");
128                 continue;
129             }
130             int op;
131             scanf("%d",&op);
132             if(ch[0]=='N')
133             {
134                 if(tree[1].sm>=op)
135                 {
136                     int st=Query(1,1,n,op);
137                     tmp.s=st, tmp.d=st+op-1;
138                     int id=find(tmp.s);
139                     vt.insert(vt.begin()+id+1,tmp);
140                     printf("New at %d\n",tmp.s);
141                     Update(1,1,n,tmp.s,tmp.d,1);  ///!!!这里注意了,查询完了还要进行相应的更新
142                 }
143                 else
144                     puts("Reject New");
145             }
146             else if(ch[0]=='G')
147             {
148                 if(vt.size()>=op)
149                     printf("Get at %d\n",vt[op-1].s);
150                 else puts("Reject Get");
151             }
152             else if(ch[0]=='F')
153             {
154                 int id=find(op);
155                 if(id==-1||vt[id].d<op) puts("Reject Free");
156                 else
157                 {
158                     Update(1,1,n,vt[id].s,vt[id].d,0);
159                     printf("Free from %d to %d\n",vt[id].s,vt[id].d);
160                     vt.erase(vt.begin()+id,vt.begin()+id+1); ///删除区间[s,d)内的元素,左闭右开
161                 }
162             }
163         }
164         puts("");
165     }
166     return 0;
167 }
原文地址:https://www.cnblogs.com/kane0526/p/2941652.html