4 条题解
-
24
#include <bits/stdc++.h> using namespace std; priority_queue<int> p; priority_queue<int,vector<int>,greater<int> > q; int m,n,a[100007],u[100007]; int main() { cin >> m >> n; for (int i = 1;i <= m;i++) { cin >> a[i]; } for (int i = 1;i <= n;i++) { cin >> u[i]; } int j = 1; for (int i = 1;i <= n;i++) { while(j<=u[i]) { p.push(a[j]); j++; q.push(p.top()); p.pop(); } p.push(q.top()); q.pop(); cout << p.top() << endl; } return 0; }
AC满分代码,求点赞!!!!!! http://oj.hetao101.com/d/extra_training/p/P1053/solution/65d88cdebe73cc1b3225c469
-
19
维护两个优先队列t和s,t里面存放最小的i个数,s里面存放剩下的数。那么每次从t里面取出最大数,即为答案。
新增数字时,先将其放入t,然后把t里面最大的数放入s,即可保证此时t里面存放的数都小于等于s里面存放的数。
由于每次询问i都加1,因此每次循环里面,往t里面加入s里面最小的数,这样就能保证每次循环t的size都加1。
核心代码
int cur = 1; for (int i = 1; i <= n; i++) { while (cur <= u[i]) { t.push(a[cur++]); s.push(t.top()); t.pop(); } t.push(s.top()); s.pop(); cout << t.top() << endl; }
-
9
思路:
- 首先,创建了一个名为"spaly"的结构体。该结构体包含了一些用于维护Splay树的数据结构和操作函数。
- 在主函数中,首先读入序列长度n和查询次数m,然后依次读入序列元素a[i]和每个元素出现的次数f[i]。
- 接下来,使用循环将每个元素插入到Splay树中,并在插入过程中进行查询并输出结果。
- 插入操作:通过循环遍历将元素逐个插入到Splay树中。在插入过程中,首先判断当前元素是否已经存在于树中。如果存在,则增加元素的计数器cnt;否则,创建一个新节点,并根据节点值大小将其插入到合适的位置。
- 查询操作:通过递归判断和比较当前节点的左子树节点数量和要查询的排名rank的关系,从而确定查询的方向(左子树还是右子树)。如果rank小于等于左子树节点数量,则递归查询左子树;否则,从右子树中查询rank减去左子树节点数量和当前节点重复次数后的排名。
- Splay操作:通过循环将当前节点旋转到目标位置。旋转操作分为单旋和双旋,具体的旋转方式取决于当前节点、父节点和祖父节点的相对位置关系。
- 最后,输出查询结果。
总结:通过插入元素并维护Splay树的结构,可以快速查询任意位置的第k大元素。该算法的时间复杂度为O(nlogn),其中n为序列的长度。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> #define MAXN 400000 using namespace std; int n, m, a[MAXN], f[MAXN], key, root, sz; struct spaly { int size[MAXN], son[MAXN][3], val[MAXN], father[MAXN], cnt[MAXN]; inline void maintain (int x) { size[x] = size[son[x][0]] + size[son[x][1]] + cnt[x]; } inline void rotate (int x) { int y = father[x], z = father[y]; int k = son[y][1] == x, kk = son[z][1] == y; son[z][kk] = x; father[x] = z; son[y][k] = son[x][k ^ 1]; father[son[x][k ^ 1]] = y; son[x][k ^ 1] = y; father[y] = x; maintain (y), maintain (x); } inline void splay (int x, int goal) { while (father[x] != goal) { int y = father[x], z = father[y]; if (z != goal) (son[y][1] == x) ^ (son[z][1] == y) ? rotate (x) : rotate (y); rotate (x); } if (! goal) root = x; } int Kth (int x, int rank) { if (son[x][0] && rank <= size[son[x][0]]) return Kth (son[x][0], rank); return (rank <= size[son[x][0]] + cnt[x]) ? x : Kth (son[x][1], rank - size[son[x][0]] - cnt[x]); } inline void insert (int x) { int now = root, fa = 0; while (now && val[now] != x) { fa = now, now = son[now][x > val[now]]; } if (now) cnt[now]++; else { now = ++sz; if (fa) son[fa][x > val[fa]] = now; son[now][0] = son[now][1] = 0, cnt[now] = size[now] = 1, father[now] = fa, val [now] = x; } splay (now, 0); } }tree; int main () { scanf ("%d%d", &n, &m); for (register int i = 1; i <= n; i++) scanf ("%d", &a[i]); for (register int i = 1; i <= m; i++) { int x; scanf ("%d", &x), f[x]++; } for (register int i = 1; i <= n; i++) { tree.insert (a[i]); for (register int j = 1; j <= f[i]; j++) printf ("%d\n", tree.val[tree.Kth (root, ++key)]); } return 0; }
记得点赞!!! 记得点赞!!! 记得点赞!!!
-
3
各位大佬的代码我看不懂我用两个优先队列
#include<bits/stdc++> using namespace std; const int MAXN = 5000+10; priority_queue<int,vector<int>,greater<int> >s; priority_queue<int,vector<int>,less<int> >b; int a[MAXN],u[MAN]; int main() { cin>>m>>n; for(int i=1; i<=m; i++) cin>>a[i]; for(int i=1; i<=n; i++) cin>>u[i]; while(n>m); while(m==n); int p=0; for(int i=1; i<=n; i++) { while(p<u[i]) { ++p; b.push(a[p]); s.push(b.top()); b.pop(); } cout<<s.top()<<"/n"; b.push(s.top()); s.pop(); } return 0; }
有防作弊
- 1
信息
- ID
- 249
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 886
- 已通过
- 436
- 上传者