题目大意:
初始只含 0 的数组,第 i 次操作,选择长度最长的 0 的连续区间
[
l
,
r
]
[l,r]
[ l , r ] ,如果
(
r
−
l
+
1
)
(r-l+1)
( r − l + 1 ) 为奇数,则
a
(
r
+
l
)
/
2
=
i
a_{(r+l)/2}=i
a ( r + l ) /2 = i ;否则,
a
(
r
+
l
−
1
)
/
2
=
i
a_{(r+l-1)/2}=i
a ( r + l − 1 ) /2 = i ; 输出最后的序列,对于一个n,序列唯一。
思路:
要求每次最长区间,且每次操作之后会产生 2 个小区间。 采用优先队列 ,存储 (node){l,r} 元素,每次操作最长区间即可,具体思路见代码。
input:
6
1
2
3
4
5
6
output:
1
1 2
2 1 3
3 1 2 4
2 4 1 3 5
3 4 1 5 2 6
code:
# include <iostream>
# include <cstring>
# include <cstdio>
# include <cmath>
# include <algorithm>
# include <queue>
# include <vector>
# include <map>
# include <set>
using namespace std;
# define Please return
# define Accepted 0
# define int long long
# define endl "\n"
typedef long long LL;
typedef pair< int , int > PII;
typedef pair< double , double > PDD;
const int N = 200010 , M= 2 * N, INF= 0x3f3f3f3f ;
int n;
struct node {
int l, r;
bool operator < ( const node y) const {
if ( r- l== y. r- y. l) return l> y. l;
return r- l< y. r- y. l;
}
} ;
priority_queue< node> q;
int a[ N] ;
void slove ( int _case)
{
while ( ! q. empty ( ) ) q. pop ( ) ;
cin>> n;
for ( int i= 1 ; i<= n; i++ ) a[ i] = 0 ;
q. push ( { 1 , n} ) ;
int cnt= 1 ;
while ( ! q. empty ( ) )
{
if ( cnt== n+ 1 ) break ;
auto t= q. top ( ) ;
if ( ( t. r- t. l+ 1 ) % 2 == 1 ) {
int mid= ( t. r+ t. l) / 2 ;
a[ mid] = cnt++ ; q. pop ( ) ;
q. push ( { t. l, mid- 1 } ) , q. push ( { mid+ 1 , t. r} ) ;
} else {
int mid= ( t. r+ t. l- 1 ) / 2 ;
a[ mid] = cnt++ , q. pop ( ) ;
q. push ( { t. l, mid- 1 } ) , q. push ( { mid+ 1 , t. r} ) ;
}
}
for ( int i= 1 ; i<= n; i++ ) cout<< a[ i] << " " ;
cout<< endl;
}
signed main ( )
{
ios_base:: sync_with_stdio ( 0 ) , cin. tie ( 0 ) , cout. tie ( 0 ) ;
int T= 1 ;
cin>> T;
for ( int _case= 1 ; _case<= T; _case++ )
{
slove ( _case) ;
}
Please Accepted;
}