【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 }

 

你可能感兴趣的:(memory)