HDU 4614 Vases and Flowers 线段树 + 二分

线段树节点记录内容请见代码注释

操作1:每次查询区间 [A, N - 1] 中第一个空格的位置,然后在[ A, N - 1 ]中二分右端点的位置。实际放的花的数量是 要求数量 与 剩余空格数量 之间的最小值

如果[ A, N - 1 ]中已经没有空格了,就不能放了。

操作2:求和与成端更新,线段树基本操作不解释

比赛的时候把PushDown函数写错了,样例死活不过,比赛结束之后才看出来,2A之,orz……要不要这么伤人……

 

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <cstdlib>

  4 #include <algorithm>

  5 

  6 #define lson l, m, rt << 1

  7 #define rson m + 1, r, rt << 1 | 1

  8 

  9 using namespace std;

 10 

 11 const int MAXN = 50010;

 12 const int INF = 1 << 30;

 13 

 14 int N, Q, ok;

 15 int flag[ MAXN << 2 ];    //无标记:-1,清空:0,占用:1

 16 int sum[ MAXN << 2 ];     //区间占用区域总和

 17 int len[ MAXN << 2 ];     //空闲区域长度总和

 18 int addr[ MAXN << 2 ];    //本区间第一个空格的位置

 19 

 20 void PushUp( int rt, int l, int r )

 21 {

 22     int lc = rt << 1;

 23     int rc = rt << 1 | 1;

 24     sum[rt] = sum[lc] + sum[rc];

 25     len[rt] = len[lc] + len[rc];

 26     addr[rt] = min( addr[lc], addr[rc] );

 27 

 28     return;

 29 }

 30 void PushDown( int rt, int l, int r )

 31 {

 32     int m = ( l + r ) >> 1;

 33     int lc = rt << 1;

 34     int rc = rt << 1 | 1;

 35     if ( flag[rt] != -1 )

 36     {

 37         flag[lc] = flag[rc] = flag[rt];

 38         if ( flag[rt] == 1 )   //如果占用

 39         {

 40             sum[lc] = m - l + 1;

 41             sum[rc] = r - m;

 42             len[lc] = len[rc] = 0;

 43             addr[lc] = addr[rc] = INF;   //本区间没有空格

 44         }

 45         else

 46         {

 47             sum[lc] = sum[rc] = 0;

 48             len[lc] = m - l + 1;

 49             len[rc] = r - m;

 50             addr[lc] = l;

 51             addr[rc] = m + 1;

 52         }

 53         flag[rt] = -1;

 54     }

 55     return;

 56 }

 57 void build( int l, int r, int rt )

 58 {

 59     flag[rt] = -1;

 60     if ( l == r )

 61     {

 62         sum[rt] = 0;

 63         len[rt] = r - l + 1;

 64         addr[rt] = l;

 65         return;

 66     }

 67     int m = ( l + r ) >> 1;

 68     build( lson );

 69     build( rson );

 70     PushUp( rt, l, r );

 71     return;

 72 }

 73 

 74 int QuerySum( int L, int R, int l, int r, int rt )

 75 {

 76     //printf( "preS: [%d, %d]: sum = %d\n", l, r, sum[rt] );

 77     if ( L <= l && r <= R ) return sum[rt];

 78     PushDown( rt, l, r );

 79 

 80     int m = ( l + r ) >> 1;

 81     int res = 0;

 82 

 83     if ( L <= m ) res += QuerySum( L, R, lson );

 84     if ( R > m )  res += QuerySum( L, R, rson );

 85     PushUp( rt, l, r );

 86 

 87     //printf( "afterS: [%d, %d]: sum = %d\n", l, r, sum[rt] );

 88     return res;

 89 }

 90 

 91 //查询大于等于st的第一个空格的位置

 92 int QueryConti( int L, int R, int l, int r, int rt )

 93 {

 94     if ( L <= l && r <= R )

 95     {

 96         return addr[rt];

 97     }

 98     PushDown( rt, l, r );

 99     int m = ( l + r ) >> 1;

100     int tmp = INF;

101 

102     if ( L <= m ) tmp = min( tmp, QueryConti( L, R, lson ) );

103     if ( R > m )  tmp = min( tmp, QueryConti( L, R, rson ) );

104 

105     PushUp( rt, l, r );

106 

107     return tmp;

108 }

109 

110 void Update( int L, int R, int c, int l, int r, int rt )

111 {

112     //printf( "pre UP [%d, %d]: sum = %d\n", l, r, sum[rt] );

113     if ( L <= l && r <= R )

114     {

115         flag[rt] = c;

116         if ( flag[rt] == 1 )   //如果占用

117         {

118             sum[rt] = r - l + 1;

119             len[rt] = 0;

120             addr[rt] = INF;   //本区间没有空格

121         }

122         else

123         {

124             sum[rt] = 0;

125             len[rt] = r - l + 1;

126             addr[rt] = l;

127         }

128         return;

129     }

130     PushDown( rt, l, r );

131 

132     int m = ( l + r ) >> 1;

133     if ( L <= m ) Update( L, R, c, lson );

134     if ( R > m )  Update( L, R, c, rson );

135     PushUp( rt, l, r );

136 

137     //printf( "after UP [%d, %d]: sum = %d\n", l, r, sum[rt] );

138     return;

139 }

140 

141 int BiSearch( int l, int r, int st, int tar )

142 {

143     //printf("tar=%d\n", tar);

144     while ( l <= r )

145     {

146         int mid = ( l + r ) >> 1;

147         int sum = QuerySum( st, mid, 0, N - 1, 1 );

148         sum = mid - st + 1 - sum;

149         if ( sum >= tar ) r = mid;

150         else l = mid + 1;

151         if ( l == r ) return l;

152     }

153     return l;

154 }

155 

156 int main()

157 {

158     //freopen( "s.out", "w", stdout );

159     int T;

160     scanf( "%d", &T );

161     while( T-- )

162     {

163         scanf( "%d%d", &N, &Q );

164         build( 0, N - 1, 1 );

165         while ( Q-- )

166         {

167             int op, a, b;

168             scanf( "%d%d%d", &op, &a, &b );

169             if ( op == 1 )

170             {

171                 if ( b == 0 ) continue;

172                 int ans = QuerySum( a, N - 1, 0, N - 1, 1 );

173                 if ( ans == N - a )

174                     puts("Can not put any one.");

175                 else

176                 {

177                     //printf( "%d %d\n", N - a, ans );

178                     int FF = min( N - a - ans, b );

179                     int left = QueryConti( a, N - 1, 0, N - 1, 1 );

180                     int right = BiSearch( a, N - 1, a, FF );

181                     printf( "%d %d\n", left, right );

182                     Update( left, right, 1, 0, N - 1, 1 );

183                 }

184             }

185             else

186             {

187                 int ans = QuerySum( a, b, 0, N - 1, 1 );

188                 printf( "%d\n", ans );

189                 Update( a, b, 0, 0, N - 1, 1 );

190             }

191             //puts("**********");

192         }

193         puts("");

194     }

195     return 0;

196 }

 

你可能感兴趣的:(HDU)