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}

按以下要求填数字:

  1. 选择最长的全0区间[L,R],把[L,R]的中点填时间戳timer
  2. 如果有多个全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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值