codeforces1353D(构造)
题意:
起初数组都是0,第i次选择最长的0的子段中最左边的子段,然后取中间值赋值为i,一直执行n次,输出赋值后的长度为n的数组
思路:
每次取最长直接可以使用堆来维护子段的长度,取最左边可以维护每个子段的左端点,同时每次分割一个子段就会生成两个新的子段
题解:
#include <bits/stdc++.h>
// #define x first
// #define y second
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define lowbit(x) x&(-x)
#define INF 0x7fffffff
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);};
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int N=200010;
struct T{//按照要求重载结构体
int x,y;
bool operator<(const T &t) const{
if(t.x!=x) return x<t.x;
return y>t.y;
}
};
int a[N];
void solve() {
memset(a,0,sizeof a);
int n;
cin>>n;
priority_queue<T> q;
q.push({n,1});
int mid;
int idx=1;
while(q.size()){
auto t=q.top();
q.pop();
int len=t.x, l=t.y;
int r=l+len-1;
if(len&1) mid=(l+r)/2;
else mid=(l+r-1)/2;
a[mid]=idx++;
if(mid-l>=1) q.push({mid-1-l+1,l});
if(r-mid>=1) q.push({r-mid,mid+1});
}
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<endl;
}
signed main() {
IOS;
int _; cin >> _; while (_--) solve();
return 0;
}