zoukankan      html  css  js  c++  java
  • HDU

    题意 

      给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个

    题解:

      写法很多,主席树是最常用的一种之一

      除此之外有:划分树,莫队分块,平衡树等

      主席树的定义其实挺模糊,

      一般认为就是可持久化线段树/函数式线段树的这种实现方式

      被用来求区间第$K$大的时候,是可持久化的权值线段树

      主席树的特点就是 $[l,r]$的区间信息可以通过创造的第$r$颗树的减去第$l-1$颗树得到

      具体思路就是:

      将数列的值进行排序,去重

      对于原序列的每一个值,依次插入可持久化的权值线段树,将它所在排序位置权值+1

      在线段树中,每一次插入实际上都会开一颗节点为$log(n)$新的线段树,树根保存为$rt_i$,存有$[1,i]$的区间信息

      然后对于每次询问$[l,r]$,$tree_r - tree_{l-1}$的第$K$个数字即为答案

      *树之间的减法是指,对于每个节点的权值进行相减

      显然$tree_{i+m}-tree_i$最终得到的树与权值,就代表了$[i+1,i+m]$之间插入的元素,也就是区间$[i+1,m]$的权值树,就可以当做数列整体第$K$大解决了

    #include <bits/stdc++.h>
    #define nd seg[now]
    #define ndp seg[pre]
    #define mid ((s+t)>>1)
    using namespace std;
    const int maxn=1e5+10;
    vector<int>pos;
    int casn,n,m,k;
    int num[maxn],rt[maxn],size;
    struct node{
    	int l,r,sum;
    }seg[maxn*20];
    void maketree(int s=1,int t=n,int &now=rt[0]){
    	now=++size;nd={s,t,0};
    	if(s==t) return ;
    	maketree(s,mid,nd.l);maketree(mid+1,t,nd.r);
    }
    void update(int &now,int pre,int k,int s=1,int t=n){
    	now=++size;nd=ndp,nd.sum++;
    	if(s==t) return ;
    	if(k<=mid)update(nd.l,ndp.l,k,s,mid);
    	else update(nd.r,ndp.r,k,mid+1,t);
    }
    int query(int now,int pre,int k,int s=1,int t=n){
    	if(s==t) return s;
    	int sum=seg[ndp.l].sum-seg[nd.l].sum;
    	if(k<=sum) return query(nd.l,ndp.l,k,s,mid);
    	else return query(nd.r,ndp.r,k-sum,mid+1,t);
    }
    int main(){
    	scanf("%d",&casn);
    	while(casn--){
    		scanf("%d%d",&k,&m);
    		pos.clear();
    		size=0;
    		for(int i=1;i<=k;i++){
    			scanf("%d",num+i);
    			pos.push_back(num[i]);
    		}
    		sort(pos.begin(),pos.end());
    		pos.erase(unique(pos.begin(),pos.end()),pos.end());
    		n=pos.size();
    		maketree(1,n,rt[0]);
    		for(int i=1;i<=k;i++){
    			int id=lower_bound(pos.begin(),pos.end(),num[i])-pos.begin()+1;
    			update(rt[i],rt[i-1],id);
    		}
    		while(m--){
    			int a,b,c;
    			scanf("%d%d%d",&a,&b,&c);
    			printf("%d
    ",pos[query(rt[a-1],rt[b],c)-1]);
    		}
    	}
      return 0;
    }

      

  • 相关阅读:
    git 学习网站
    Vue 部署在 IIS 上
    Element UI 的坑
    Vue 中 Prop 传至的 一个Bug
    Asp.net Core 部署在 IIS上
    今天用UniApp开发, 用到 Vuex 中的 mutations, 设置值的时候好像只能传2个参数, 第一个是固定的state, 第二个是一个值, 不能传第三个了
    anxios 和 uni.request 访问Asp.net 服务器传参出错的坑
    内网计算机设置问题说明
    关于综合布线
    Android学习 -- Activity 以及Activity之间值传递
  • 原文地址:https://www.cnblogs.com/nervendnig/p/9197142.html
Copyright © 2011-2022 走看看