【题目翻译】
给你一个长度为n的连续0,你现在可以每次把其中一段的最中间那个位置的数字改为++cur(cur初值为0) 但是你每次选取的一段需要满足这样的要求: 1.是一个连续的最大0段。 2.这个0段的长度是最长的。 3.这个0段是最靠左的。【题解】
定义个长度为n的priorityqueue数组,每个数组中按照左端点递增的顺序放0段。且数组第i个位置上的优先队列放长度为i的0段的起始位置。 然后按照0段的长度由大到小模拟这个分解的过程就好(每个0段会分解成两个部分)。【代码】
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5;
struct node{
int l,r;
node *_next;
};
priority_queue<int,vector<int>,greater<int> > sta[N+10];
int T,n,a[N+10],cur;
void handleRange(int l,int r){
int len = r-l+1;
if (len<=0) return;
sta[len].push(l);
}
int main(){
#ifdef LOCAL_DEFINE
freopen("D:\rush.txt","r",stdin);
#endif
scanf("%d",&T);
while(T--){
cur = 0;
scanf("%d",&n);
sta[n].push(1);
for (int i = n;i>=1;i--){
while (!sta[i].empty()){
int l = sta[i].top(),r = l+i-1,mid = (l+r)/2;
sta[i].pop();
a[mid] = ++cur;
handleRange(l,mid-1);
handleRange(mid+1,r);
}
}
for (int i = 1;i <= n;i++){
printf("%d",a[i]);
if (i==n) puts("");else putchar(' ');
}
}
return 0;
}