4 条题解

  • 24
    @ 2024-2-23 20:17:34
    #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
      @ 2023-7-6 16:14:28

      维护两个优先队列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;
      }
      
      • @ 2023-8-8 12:24:10

        简单易懂

      • @ 2023-8-10 19:45:50

        哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇!!!! 管理员,你那个下拉菜单怎么做的~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

      • @ 2023-8-15 15:55:45

        👍👍👍❤️ 😄

      • @ 2023-8-17 14:13:59

        you did a good job!

      • @ 2023-10-14 14:33:36

        简单易懂

    • 9
      @ 2023-7-21 23:23:19

      思路:

      1. 首先,创建了一个名为"spaly"的结构体。该结构体包含了一些用于维护Splay树的数据结构和操作函数。
      2. 在主函数中,首先读入序列长度n和查询次数m,然后依次读入序列元素a[i]和每个元素出现的次数f[i]。
      3. 接下来,使用循环将每个元素插入到Splay树中,并在插入过程中进行查询并输出结果。
      4. 插入操作:通过循环遍历将元素逐个插入到Splay树中。在插入过程中,首先判断当前元素是否已经存在于树中。如果存在,则增加元素的计数器cnt;否则,创建一个新节点,并根据节点值大小将其插入到合适的位置。
      5. 查询操作:通过递归判断和比较当前节点的左子树节点数量和要查询的排名rank的关系,从而确定查询的方向(左子树还是右子树)。如果rank小于等于左子树节点数量,则递归查询左子树;否则,从右子树中查询rank减去左子树节点数量和当前节点重复次数后的排名。
      6. Splay操作:通过循环将当前节点旋转到目标位置。旋转操作分为单旋和双旋,具体的旋转方式取决于当前节点、父节点和祖父节点的相对位置关系。
      7. 最后,输出查询结果。

      总结:通过插入元素并维护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
      @ 2023-11-12 10:45:34

      各位大佬的代码我看不懂我用两个优先队列

      #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
      上传者