线段树节点记录内容请见代码注释
操作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 }