codeforces1353D(构造)

1353D

题意:

起初数组都是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;
}
posted @ 2021-10-04 23:08  指引盗寇入太行  阅读(32)  评论(0编辑  收藏  举报