• 利用双堆维护第K大元素之Black box


    #include<bits/stdc++.h>
    #define N 200005
    using namespace std;
    int m,n,k;
    int a[N],b[N],u[N];
    struct MM{
        int l,r,s;
    }tree[N<<2];
    inline void build(int root,int L,int R)
    {
        tree[root].l=L;
        tree[root].r=R;
        if(L==R) return;
        int mid=(L+R)>>1;
        build(root<<1,L,mid);
        build(root<<1|1,mid+1,R);
    }
    inline void update(int root,int t)
    {
        if(tree[root].l==tree[root].r)
        {
            tree[root].s++;//个数加一
            return;
        }
        int mid=(tree[root].l+tree[root].r)>>1;
        if(t<=mid) 
           update(root<<1,t);
        else 
              update(root<<1|1,t);
        tree[root].s=tree[root<<1].s+tree[root<<1|1].s;
    }
    inline int query(int root,int t)
    {
        if(tree[root].l==tree[root].r)
            return tree[root].l;
        if(t<=tree[root<<1].s) 
    	    return query(root<<1,t);
        else 
    	     return query(root<<1|1,t-tree[root<<1].s);
    }
    int main()
    {
        cin>>m>>n;//m个数字,n个询问 
        for(int i=1;i<=m;i++)
        {
            cin>>a[i];
            b[i]=a[i];
        }
        for(int i=1;i<=n;i++)
            cin>>u[i];
        sort(b+1,b+m+1);
        int s=unique(b+1,b+m+1)-(b+1);
       //离散化,s是数组b中不重复的数的个数
        build(1,1,s);//依s建树
        int h=0;
        while(n!=h)//依次查询 
        {
            h++;
            for(int i=u[h-1]+1;i<=u[h];i++)//将指定区间数字加入权值线段树 
            {
                int v=lower_bound(b+1,b+s+1,a[i])-b;
       	         //v是a[i]在数组b中所处的位置(注意之前数组b排了序)
                update(1,v);
            }
            cout<<b[query(1,++k)]<<endl;
        }
        return 0;
    }
    

      

    #include<cstdio>
    #include<queue>
    using namespace std;
    int a[30001],b[30001];
    int s,m,n,x,y,i,j,k;
    int main() {
    	scanf("%d",&s);
    	for(k=1; k<=s; k++)     {
    		j=1;
    		priority_queue<int>q1; //大根堆 
    		priority_queue<int,vector<int>,greater<int> >q2;
    		//小根堆 
    		scanf("%d%d",&m,&n);
    		for(i=1; i<=m; i++)             
    		    scanf("%d",&a[i]);
    		for(i=1; i<=n; i++)             
    		    scanf("%d",&b[i]);
    		for(i=1; i<=n; i++)         
    		{
    			for(; j<=b[i]; j++)   
    			//将前b[i]个数字放入小根堆             
    			    q2.push(a[j]);
    			while(q1.size()<i)   
    			//保证大根堆中有i个元素          
    			{
    				q1.push(q2.top());
    				q2.pop();
    			}
    			while(!q2.empty()&&q1.top()>q2.top())  
    			//互换堆顶元素           
    			{
    				x=q1.top();
    				y=q2.top();
    				q1.pop();
    				q2.pop();
    				q1.push(y);
    				q2.push(x);
    			}
    			printf("%d\n",q1.top());
    		}
    		if(k!=s)printf("\n");
    	}
    }
    

      

  • 相关阅读:
    模板方法模式
    备忘录模式
    观察者模式
    中介者模式
    迭代器模式
    Char型和string型字符串比较整理
    命令模式
    责任链模式
    代理模式
    dokcer 杂谈
  • 原文地址:https://www.cnblogs.com/cutemush/p/11789049.html
Copyright © 2020-2023  润新知