zoukankan      html  css  js  c++  java
  • codeforces 1262D Optimal Subsequences 主席树询问第k小

    题意

    给定长度为(n)的序列(a),以及m个询问(<k,pos>),每次询问满足下列条件的子序列中第(pos)位的值为多少。

    • 子序列长度为(k)
    • 序列和是所有长度为(k)的子序列中最大的
    • 字典序是所有满足上述两个条件的序列中最小的

    解题思路

    稍作分析即可得出,将序列按值的大小作为第一关键字(升序),下标作为第二关键字(降序)排序,所得序列的后(k)个元素即为询问长度为(k)时满足给定条件的序列中的元素,所以答案就是后(k)个元素中下标第(pos)小的元素的值,用主席树维护即可。

    AC代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5;
     
    int n,m,t[maxn];
    struct node{
    	int v,id;
    	bool operator<(const node& nd){
    		if(v==nd.v)return id>nd.id;
    		return v<nd.v;	
    	}
    }a[maxn];
     
    int T[maxn],tot;
    int sum[maxn<<5],L[maxn<<5],R[maxn<<5];
    int update(int rt,int l,int r,int p){
    	int nrt=++tot;
    	L[nrt]=L[rt]; R[nrt]=R[rt]; sum[nrt]=sum[rt]+1;
    	if(l!=r){
    		int mid=(l+r)>>1;
    		if(p<=mid)L[nrt]=update(L[rt],l,mid,p);
    		else R[nrt]=update(R[rt],mid+1,r,p);
    	}
    	return nrt;
    }
     
    int query(int u,int v,int l,int r,int k){
    	if(l==r)return l;
    	int cnt=sum[L[v]]-sum[L[u]];
    	int mid=(l+r)>>1;
    	if(k<=cnt)return query(L[u],L[v],l,mid,k);
    	else return query(R[u],R[v],mid+1,r,k-cnt);
    }
     
    int main()
    {
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i].v);
    		a[i].id=i;	t[i]=a[i].v;
    	}
    	sort(a+1,a+1+n);
    	
    	for(int i=1;i<=n;i++)T[i]=update(T[i-1],1,n,a[i].id);
    	int k,pos;
    	scanf("%d",&m);
    	while(m--){
    		scanf("%d %d",&k,&pos);	
    		printf("%d
    ",t[query(T[n-k],T[n],1,n,pos)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Python中获取异常(Exception)信息
    python中的构造函数和析构函数
    windows下python检查文件是否被其它文件打开
    python怎样压缩和解压缩ZIP文件
    Python递归遍历《指定目录》下的所有《文件》
    HTML基础知识(w3school)
    关于c#除法运算的问题
    WPF如何给窗口Window增加阴影效果
    图片加载,创建事件监听
    版本回退的冲突问题
  • 原文地址:https://www.cnblogs.com/zengzk/p/11934258.html
Copyright © 2011-2022 走看看