【Codeforces Round #642 (Div. 3)】Constructing the Array

题目链接

【题目翻译】

给你一个长度为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;
}

猜你喜欢

转载自www.cnblogs.com/AWCXV/p/12941512.html