Codeforces Round #642 (Div. 3) D. Constructing the Array
D. Constructing the Array
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a of length n consisting of zeros. You perform n actions with this array: during the i-th action, the following sequence of operations appears:
Choose the maximum by length subarray (continuous subsegment) consisting only of zeros, among all such segments choose the leftmost one;
Let this segment be [l;r]. If r−l+1 is odd (not divisible by 2) then assign (set) a[l+r2]:=i (where i is the number of the current action), otherwise (if r−l+1 is even) assign (set) a[l+r−12]:=i.
Consider the array a of length 5 (initially a=[0,0,0,0,0]). Then it changes as follows:
Firstly, we choose the segment [1;5] and assign a[3]:=1, so a becomes [0,0,1,0,0];
then we choose the segment [1;2] and assign a[1]:=2, so a becomes [2,0,1,0,0];
then we choose the segment [4;5] and assign a[4]:=3, so a becomes [2,0,1,3,0];
then we choose the segment [2;2] and assign a[2]:=4, so a becomes [2,4,1,3,0];
and at last we choose the segment [5;5] and assign a[5]:=5, so a becomes [2,4,1,3,5].
Your task is to find the array a of length n after performing all n actions. Note that the answer exists and unique.
You have to answer t independent test cases.
Input
The first line of the input contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.
The only line of the test case contains one integer n (1≤n≤2⋅105) — the length of a.
It is guaranteed that the sum of n over all test cases does not exceed 2⋅105 (∑n≤2⋅105).
Output
For each test case, print the answer — the array a of length n after performing n actions described in the problem statement. Note that the answer exists and unique.
Example
inputCopy
6
1
2
3
4
5
6
outputCopy
1
1 2
2 1 3
3 1 2 4
2 4 1 3 5
3 4 1 5 2 6
Codeforces Round #642 (Div. 3) D. Constructing the Array
给定一个长度为n的数组,开始时数组为全0, arr[ ] = {0,0,0,…0}
按以下要求填数字:
- 选择最长的全0区间[L,R],把[L,R]的中点填时间戳timer
- 如果有多个全0区间[L,R],就优先填最左边的区间
打印构造好的数组
-
用堆模拟,结构体先按区间长度排序,再按左端点排
-
每次填好mid后,把区间[L,R]切分成两段[L,mid-1]和[mid+1,R],再入堆
-
推荐_heyuhhh_大佬的B站讲题视频
-
https://www.bilibili.com/video/BV1Wt4y1C7ws?p=4
struct Node {
int lef, rig;
bool operator < (const Node& no) const {
int len = rig - lef + 1;
int nolen = no.rig - no.lef + 1;
return len == nolen ? lef > no.lef : len < nolen;
}
} ;
priority_queue<Node> q;
memset(a, 0, sizeof(a));
int lef = 1, rig = n, timer = 0;
q.push({lef, rig});
while(!q.empty()) {
Node no = q.top(); q.pop();
int mid = ((no.rig+no.lef)>>1);
a[mid] = ++ timer;
if(no.lef == no.rig) continue ;
if(mid-1 >= no.lef) q.push({no.lef, mid-1});
if(mid+1 <= rig) q.push({mid+1, no.rig});
}
for(int i=1; i<=n; i++)
printf("%d%c", a[i], i==n ? '\n':' ');
完整代码
//#define debug
#ifdef debug
#include <time.h>
#include "/home/majiao/mb.h"
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#define MAXN ((int)2e5+7)
#define ll long long int
#define INF (0x7f7f7f7f)
#define QAQ (0)
using namespace std;
#ifdef debug
#define show(x...) \ do { \ cout << "\033[31;1m " << #x << " -> "; \ err(x); \ } while (0)
void err() { cout << "\033[39;0m" << endl; }
#endif
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
int n, m, Q, K, a[MAXN];
struct Node {
int lef, rig;
//先按区间长度排序,长度相同按左端点排序
bool operator < (const Node& no) const {
int len = rig - lef + 1;
int nolen = no.rig - no.lef + 1;
return len == nolen ? lef > no.lef : len < nolen;
}
} ;
int main() {
#ifdef debug
freopen("test", "r", stdin);
clock_t stime = clock();
#endif
#if 0
priority_queue<Node> q;
q.push({1, 2});
q.push({4, 4});
while(!q.empty()) {
auto now = q.top();
show(now.lef, now.rig);
q.pop();
}
#else
scanf("%d ", &Q);
while(Q--) {
scanf("%d ", &n);
priority_queue<Node> q;
memset(a, 0, sizeof(a));
int lef = 1, rig = n, timer = 0;
q.push({lef, rig}); //初始区间是[1,n]
while(!q.empty()) {
Node no = q.top(); q.pop();
int mid = ((no.rig+no.lef)>>1);
// show(no.lef, no.rig, (no.rig-no.lef+1));
a[mid] = ++ timer;
if(no.lef == no.rig) continue ; //这个区间只有一个数字就
//就不用往下切分了
//记得减一,因为mid已经填过数字了
if(mid-1 >= no.lef) q.push({no.lef, mid-1});
if(mid+1 <= rig) q.push({mid+1, no.rig});
}
for(int i=1; i<=n; i++)
printf("%d%c", a[i], i==n ? '\n':' ');
// forarr(a, 1, n);
}
#endif
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}