Question
给你一串长度为 n n n,值为 0 0 0的数组,每次找到最长 0 0 0子串,将其中间(奇数中间 L + R 2 \frac{L+R}{2} 2L+R,若为偶数则选 L + R − 1 2 \frac{L+R-1}{2} 2L+R−1)
Solution
优先队列模拟
利用优先队列保存
[
L
,
R
]
[L,R]
[L,R],每次保存去掉其中间之后的满足题意的子区间
[
L
,
m
i
d
−
1
]
[L,mid-1]
[L,mid−1],
[
m
i
d
+
1
,
R
]
[mid+1,R]
[mid+1,R]
优先队列是用运算符 < < <,但是排序的顺序和sort是相反的,所以里面的符号要和sort时用的写起来相反即可。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const ll N = 2e5 + 5;
struct node{
int l,r;
bool operator < (const node &T) const{
if(r-l==T.r-T.l) return r>T.r;
return r-l<T.r-T.l;
}
};
void solve(){
int n;cin>>n;
priority_queue<node>q;
q.push({1,n});
int cnt=0;
vector<int> a(n+1);
while(!q.empty()){
cnt++;
int L=q.top().l;
int R=q.top().r;
q.pop();
int mid;
if((R-L+1)&1)
mid=(L+R)/2;
else
mid=(L+R-1)/2;
a[mid]=cnt;
if(L<=mid-1 && L>=1) q.push({L,mid-1});
if(R>=mid+1 && R<=n) q.push({mid+1,R});
}
for(int i=1;i<=n;i++){
cout<<a[i]<<" \n"[i==n];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}