-
题意:有一个长度为\(n\)元素均为\(0\)的序列,进行\(n\)次操作构造出一个新序列\(a\):每次选择最长的连续为\(0\)的区间\([l,r]\),使得第\(i\)次操作时,\(a[\frac{l+r}{2}]=i\)(下取整),求\(a\).
-
题解:刚开始我打算用归并分治的思想来写,但是发现左区间递归不到,然后就gg了.
之后才发现这题用_优先队列_直接模拟就过了,题目就不说了,这儿讲一下优先队列.
优先队列与队列的区别在于,优先队列是按照某种优先级来决定谁在队头,C++默认它是一个大根堆,但是我们往往需要自己来定义优先级,所以我们就可以用一个结构体来重载运算符,再结合堆的性质来理解就好了.
-
代码
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #include <unordered_set> #include <unordered_map> #define ll long long #define fi first #define se second #define pb push_back #define me memset const int N = 1e6 + 10; const int mod = 1e9 + 7; using namespace std; typedef pair<int,int> PII; typedef pair<long,long> PLL; int t; int n; int ans[N]; int cnt; struct Node{ int l,r; bool operator < (const Node &w)const{ if(r-l==w.r-w.l) return l>w.l; else return r-l<w.r-w.l; } }; int main() { ios::sync_with_stdio(false); cin>>t; while(t--){ cin>>n; cnt=0; priority_queue<Node> q; q.push({1,n}); while(!q.empty()){ auto cmp=q.top(); q.pop(); int l=cmp.l; int r=cmp.r; int mid=l+r>>1; ans[mid]=++cnt; if(l!=mid) q.push({l,mid-1}); if(r!=mid) q.push({mid+1,r}); } for(int i=1;i<=n;++i) printf("%d ",ans[i]); puts(""); } return 0; }